我已经看到了很多答案,如何创建(例如)A
类,其中包含对象B b
和B
类,其中包含对象A a
像:
B:
class A;
class B{
A& a;
};
A:
class A{
B b;
};
但如果我想在A
B
中调用Invalid use of incomplete type 'class A'
中的函数,我得到:#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
我能做什么?我想我知道编译器为什么这么说,但我不知道如何修复它。
这是我最新的代码:
Main.cpp的:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print() { sub.print(); }
void printTest() { std::cout << "test" << std::endl; }
};
#endif
MainClass.h:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print() { main->printTest(); }
protected:
private:
};
#endif
SubClass.h:
# --table-start--
dataClass=com.icecube.iceman.model.dto.AddressEntity
tableName=address
# --table-fields-start--
fieldName=id
columnName=_id
generatedId=true
fieldName=name
columnName=name
fieldName=zip
columnName=zip
fieldName=country
columnName=country
fieldName=city
columnName=city
fieldName=district
columnName=district
fieldName=street
columnName=street
fieldName=streetnumber
columnName=streetNumber
fieldName=block
columnName=block
fieldName=building
columnName=building
fieldName=type
columnName=type
# --table-fields-end--
# --table-end--
答案 0 :(得分:2)
您的代码的主要问题是MainClass和SubClass的定义是相互依赖,因此使用标头保护将禁止在同一转换中包含两个头文件单位(即cpp文件和所有包含的头文件的并集。)
子类中的类MainClass的前向声明可以解决这个问题,因为SubClass :: main是一个指针(检查PIMPL惯用语),但是因为你已经在头文件中包含了类方法的实现文件,当SubClass :: print()方法引用MainClass :: printTest()时编译器失败,因为它对类MainClass一无所知,除了它在其他地方定义的事实。
另一方面,如上所述,由于标题保护,在子类h中明确包含mainclass.h来更改前向声明不是解决方案。
简单的解决方案是在.h和.cpp文件中拆分声明和类的实现。如果这样做,编译器将处理多个转换单元:一个用于mainclass.cpp,一个用于subclass.cpp,一个用于main.cpp。在处理subclass.cpp转换单元时,编译器将能够包含mainclass.h文件,并将MainClass的完整定义设置为&#34;参见&#34;一个MainClass :: printTest()方法存在。
这是mainclass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print();
void printTest();
};
#endif
mainclass.cpp文件:
#include <iostream>
#include "mainclass.h"
void MainClass::print()
{
sub.print();
}
void MainClass::printTest()
{
std::cout << "test" << std::endl;
}
subclass.h文件:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
};
#endif
subclass.cpp:
#include "mainclass.h"
//#include "subclass.h" // already included with the previous line
void SubClass::print()
{
main->printTest();
}
最后是main.cpp:
#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
这将编译并将显然工作,因为它将打印字符串&#34; test&#34;即使主指针未初始化,也指向未定义的内存区域。
这是因为printTest方法只会产生副作用,即在屏幕上打印。实际上,它不会通过this
指针访问MainClass的任何数据成员,因此您没有内存访问冲突。实际上,在未实例化的指针上调用方法是一种未定义的行为,因此最好避免它,以及循环依赖。
答案 1 :(得分:1)
避免在H文件中创建函数体,并将函数体放入Cpp文件中。
MainClass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass {
SubClass sub;
public:
void print();
void printTest();
};
#endif
MainClass.cpp:
#include <iostream>
#include "mainclass.h"
void MainClass :: print () { sub.print(); }
void MainClass :: printTest() {std::cout << "test" << std::endl; }
SubClass.h
#ifndef SUBCLASS_H
#define SUBCLASS_H
#include "mainclass.h"
class SubClass
{
MainClass* main;
public:
void print();
protected:
private:
};
#endif
SubClass.cpp
#include "mainclass.h"
#include "subclass.h"
void SubClass::print ()
{
main->printTest();
}
你实际上可以在你的subclass.h中#include“mainclass.h”,因为它是由#ifdef
守护的答案 2 :(得分:1)
您无法调用尚不存在的函数(MainClass::printTest
)。
您可以在SubClass
内声明该功能,但在您拥有MainClass
定义后对其进行定义。
#include <iostream>
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
protected:
private:
};
class MainClass
{
SubClass sub;
public:
void print() { sub.print(); }
void printTest() { std::cout << "test" << std::endl; }
};
void SubClass::print() { main->printTest(); }
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
答案 3 :(得分:0)
您遇到了设计问题: -
SubClass.h
编译器如何知道类MainClass有一个方法printTest
,因此它可以链接到它,因为你没有包含{{1}定义的头文件}
另一个问题是,您甚至无法在MainClass
中加入MainClass.h
,因为您在其中引用了SubClass.h
。
SubClass sub;
指针MainClass* main;
从未初始化,因此此语句main
在这里也是错误的。