C++ “前应为类名”;{“标记”
到目前为止,我已经查找了大多数针对这种错误的典型解决方案,但似乎没有一个能与我的代码一起工作++ 问题类的结构如下。 m、 嗯C++ “前应为类名”;{“标记”,c++,C++,到目前为止,我已经查找了大多数针对这种错误的典型解决方案,但似乎没有一个能与我的代码一起工作++ 问题类的结构如下。 m、 嗯 #ifndef M#H #定义M_H #包括“z.hh” #包括 #包括 使用名称空间std; M类:公共Z类 {/*编译器将此行标记为错误*/ 空m1(); 空隙m2(); }; #恩迪夫 m、 cpp #包括 #包括 #包括“m.hh” 使用名称空间std; void M::m1(){/*bla*/}; void M::m2(){/*bla*/}; } 编辑:
#ifndef M#H
#定义M_H
#包括“z.hh”
#包括
#包括
使用名称空间std;
M类:公共Z类
{/*编译器将此行标记为错误*/
空m1();
空隙m2();
};
#恩迪夫
m、 cpp
#包括
#包括
#包括“m.hh”
使用名称空间std;
void M::m1(){/*bla*/};
void M::m2(){/*bla*/};
}
编辑:
z、 嗯
#ifndef Z#H
#定义Z_H
#包括“m.hh”
#包括
#包括
使用名称空间std;
Z类;
静态Z*s(字符串g、字符串i);
#恩迪夫
z、 cpp
#包括“z.hh”
#包括
#包括
Z类
{
公众:
第i串;
字符串g;
无效集_i(字符串im){i=im;}
字符串get_i(){return i;}
字符串get_g(){return g;}
虚空m1()=0;
虚空m2()=0;
Z*s(字符串g、字符串i){
Z*Z;
如果(g=“m”){
M*z=新的M;
}
}
};
谢谢 问题 不能从不完整的类型派生,这就是
m.hh
中的Z
类型
从类型派生时,编译器必须知道所述类型的定义。试想一下,您正试图在类型为M
的对象上从Z
调用派生成员函数,而不知道Z
是否实际声明了这样的成员,编译器如何知道这样的调用是否是有效的构造
还有一个更相关的问题,M
如何能够在不知道Z
是什么的情况下初始化Z
解决方案
将
类Z
的定义移动到Z.hh
,并将其成员函数的定义保留在Z.cpp
中(与将M
拆分为M.hh
和M.cpp
的方式相同)。
不能从不完整的类型派生,这就是m.hh
中的Z
类型
从类型派生时,编译器必须知道所述类型的定义。试想一下,您正试图在类型为M
的对象上从Z
调用派生成员函数,而不知道Z
是否实际声明了这样的成员,编译器如何知道这样的调用是否是有效的构造
还有一个更相关的问题,M
如何能够在不知道Z
是什么的情况下初始化Z
解决方案
将
类Z
的定义移动到Z.hh
,并将其成员函数的定义保留在Z.cpp
中(与在M.hh
和M.cpp
之间拆分M
的方式相同)。删除\35;包括“M.hh”从z.hh
中删除#从z.hh中删除“m.hh”
以修复循环包含。那么,z.cpp文件实际上是一个类声明,应该是一个头文件。只有在处理指向该类的指针时,前向十分位才足够,但对于从一个类继承则不够(编译器确实需要知道z的类布局)
实际上并不需要z.hh,其中的函数声明也不是您所想的(它不是成员函数声明)。您可以删除它并将z.cpp重命名为z.hh
好的,与@Luchian Grigore的交流让我意识到你可能想要什么,以及为什么你有“两个z.hh”。Z将生成一个M,但M继承自Z,因此存在循环依赖关系。在C/C++中,打破这种循环的方法是限制一个类需要从另一个类知道什么:为了声明一个成员函数s,它生成一个指向新的MZ类声明的指针,只需要一个类型名M,而不是整个类声明的类型名M。因此,只需在Z的声明中引入类型名M的前向声明(classm;
)就足够了;如果指向M对象的指针作为指向基Z的指针返回,则在声明Z时根本不需要M的名称
工厂函数的定义(无论是静态文件还是成员函数)需要,如果它要生成一个M,M的完整声明。这将在一个seapate cpp文件中,该文件将包含一个完整的头文件和M的完整声明。好的,z.cpp文件实际上是一个类声明,应该是一个头文件。只有在处理指向该类的指针时,前向十分位才足够,但对于从一个类继承则不够(编译器确实需要知道z的类布局)
实际上并不需要z.hh,其中的函数声明也不是您所想的(它不是成员函数声明)。您可以删除它并将z.cpp重命名为z.hh
好的,与@Luchian Grigore的交流让我意识到你可能想要什么,以及为什么你有“两个z.hh”。Z将生成一个M,但M继承自Z,因此存在循环依赖关系。在C/C++中,打破这种循环的方法是限制一个类需要从另一个类知道什么:为了声明一个成员函数s,它生成一个指向新的MZ类声明的指针,只需要一个类型名M,而不是整个类声明的类型名M。因此,只需在Z的声明中引入类型名M的前向声明(classm;
)就足够了;如果指向M对象的指针作为指向基Z的指针返回,则在声明Z时根本不需要M的名称
工厂函数的定义(无论是静态文件还是成员函数)需要,如果它要生成一个M,M的完整声明。那将是在一个s
#ifndef M_H
#define M_H
#include "z.hh"
#include <iostream>
#include <string>
using namespace std;
class M: public Z
{ /* this line is marked by the compiler as errorneous */
void m1();
void m2();
};
#endif
#include <iostream>
#include <string>
#include "m.hh"
using namespace std;
void M::m1() {/*bla bla*/};
void M::m2() {/*bla bla*/};
}
#ifndef Z_H
#define Z_H
#include "m.hh"
#include <iostream>
#include <string>
using namespace std;
class Z;
static Z* s(string g, string i);
#endif
#include "z.hh"
#include <iostream>
#include <string>
class Z
{
public:
string i;
string g;
void set_i(string im) {i = im;}
string get_i() {return i;}
string get_g() {return g;}
virtual void m1()=0;
virtual void m2()=0;
Z* s(string g, string i) {
Z * z;
if(g=="m"){
M * z = new M;
}
}
};