我已经看到了很多答案,如何使用对象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/

10-12 20:16