到目前为止,我已经查找了大多数针对此错误案例的典型解决方案,但其中没有这些解决方案似乎适用于我的代码。我正在使用dev-c ++
有问题的课程的结构如下。 m.hh
#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
m.cpp
#include <iostream>
#include <string>
#include "m.hh"
using namespace std;
void M::m1() {/*bla bla*/};
void M::m2() {/*bla bla*/};
}
编辑: z.hh
#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
z.cpp
#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;
}
}
};
谢谢!
答案 0 :(得分:3)
从#include "m.hh"
移除z.hh
以修复循环包含。
答案 1 :(得分:2)
问题
您无法从不完整的类型派生,Z
位于m.hh
。
从类型派生时,编译器必须知道所述类型的定义。想象一下,你试图从类型Z
的对象上调用M
的派生成员函数,编译器如何知道这样的调用是否是一个有效的构造,而不知道Z
是否实际声明这样的成员?
更相关的一点是,M
如何在不知道Z
是什么的情况下初始化Z
?
解决方案
将class Z
的定义移至z.hh
,并将其成员函数的定义保留在z.cpp
中(与M
分开m.hh
的方式相同}和m.cpp
)。
答案 2 :(得分:1)
嗯,z.cpp文件实际上是一个类声明,应该是一个头文件。当你处理指向该类的指针时,前向decalaration就足够了,但不能继承一个指针(编译器确实需要知道z的类布局)。
实际上并不需要z.hh,并且其中的函数声明不是您的想法(它不是成员函数声明)。您可以删除它并将z.cpp重命名为z.hh。
好的,与@Luchian Grigore的交流让我意识到你可能想要的东西以及为什么你有两个z.hh&#34;。 Z是产生M,但M继承自Z,因此存在循环依赖。在C / C ++中,打破这样一个循环的方法是限制其中一个类需要知道的另一个:为了声明一个成员函数s,它产生一个指向新M Z的类声明只需要一个类型名M,而不是整个类声明。所以只需要在Z的声明中引入类型名称M的前向声明(class M;
)就足够了;如果指向M对象的指针作为指向基础的指针返回,则当Z 声明时,甚至根本不需要Z,M的名称。
工厂函数的定义(无论是文件静态还是成员函数)需要,如果要生成M,M的完整声明。这将是一个seaparate cpp文件,其中包含一个包含M&#39完整声明的完整标题。