我已经看到了很多答案,如何使用对象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'
我能做什么?我想我知道编译器为什么这么说,但是我不知道如何解决它。这是我的最新代码:
Main.cpp:
#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
MainClass.h:
#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
SubClass.h:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print() { main->printTest(); }
protected:
private:
};
#endif
最佳答案
您的代码的主要问题是MainClass和SubClass的定义是相互依赖的,因此,使用 header 保护符将禁止将两个 header 文件包含在同一个转换单元中(即cpp文件的并集)以及所有的头文件。)
subClass.h中MainClass类的前向声明可以解决此问题,因为SubClass::main是一个指针(检查PIMPL惯用语),但是由于您在头文件中包括了class方法的实现,因此当SubClass::print()方法引用MainClass::printTest()时,编译器将失败,因为它对MainClass类一无所知,只是在其他地方定义了它。
另一方面,如上所述,由于在 header 保护中,将mainclass.h显式包含在subclass.h中来更改前向声明不是解决方案。
简单的解决方案是在.h和.cpp文件中拆分类的声明和实现。如果这样做,编译器将在多个翻译单元上工作:一个用于mainclass.cpp,一个用于subclass.cpp,一个用于main.cpp。在处理subclass.cpp转换单元时,编译器将能够包含文件mainclass.h,并且具有MainClass的完整定义,以“看到” 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;
}
这将进行编译,并且显然可以使用起作用,因为即使未初始化主指针,它也会打印字符串“test”,并指向未定义的存储区域。
发生这种情况是因为printTest方法除了产生副作用(即在屏幕上打印)外什么都不做。实际上,它无法通过
this
指针访问MainClass的任何数据成员,因此您没有内存访问冲突。实际上,在未实例化的指针上调用方法是未定义的行为,因此最好避免使用它以及循环依赖项。关于c++ - 使用子类在MainClass中调用函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49818321/