我已经看到了许多答案,如何使用对象B b创建(例如)B b类,以及使用对象A a创建B类。
像这样:
B:
class A;
class B{
A& a;
};答:
class A{
B b;
};但是,如果我想调用A in 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次类h:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print() { main->printTest(); }
protected:
private:
};
#endif发布于 2018-04-13 15:57:04
代码的主要问题是,MainClass和SubClass的定义是相互依赖的,因此使用头保护将禁止在同一个翻译单元中包含两个头文件(即cpp文件和包含的所有头文件的结合)。
子类MainClass在.h中的前向声明可以解决这个问题,因为子类::MainClass是一个指针(请检查PIMPL成语),但是由于在头文件中包含了类方法的实现,所以当子类::print()方法引用MainClass::printTest()时编译器失败,因为它只知道类MainClass是在其他地方定义的。
另一方面,在子类h中显式包含mainclass.h来更改前向声明并不是一个解决方案,因为前面已经提到了头保护。
简单的解决方案是在.h和.cpp文件中拆分类的声明和实现。如果这样做,编译器将处理多个翻译单元:一个用于mainclass.cpp,一个用于subclass.cpp,另一个用于main.cpp。在处理subclass.cpp翻译单元时,编译器将能够包含文件mainclass.h,并具有完整的MainClass定义,以“查看”存在一个MainClass::printTest()方法。
这是主要的课程:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print();
void printTest();
};
#endifmainclass.cpp文件:
#include <iostream>
#include "mainclass.h"
void MainClass::print()
{
sub.print();
}
void MainClass::printTest()
{
std::cout << "test" << std::endl;
}子类.h文件:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
};
#endifsubclass.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方法只会产生副作用,即在屏幕上打印。实际上,它不通过MainClass指针访问this的任何数据成员,因此没有内存访问冲突。实际上,在未实例化的指针上调用方法是一种未定义的行为,因此最好避免它以及循环依赖关系。
发布于 2018-04-13 13:44:55
避免在H文件中创建函数体,并将函数体放入Cpp文件中。
MainClass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass {
SubClass sub;
public:
void print();
void printTest();
};
#endifMainClass.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:
};
#endifSubClass.cpp
#include "mainclass.h"
#include "subclass.h"
void SubClass::print ()
{
main->printTest();
}实际上,您可以在子类中包括"mainclass.h“,因为它由#ifdef保护。
发布于 2018-04-13 13:45:00
您无法调用一个尚未存在的函数(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;
}https://stackoverflow.com/questions/49818321
复制相似问题