首页 > 解决方案 > 两个类之间的交叉访问

问题描述

我有两个类都必须互相调用公共方法。问题是必须首先定义其中一个类。因此,当我定义一个类时,它必须调用另一个尚未定义的类的方法。B 类的前向声明也无济于事。这样编译器只知道类 B 存在,但不知道它有哪些成员。但是当 changeB() 被定义时,编译器需要知道它们。

这里是一个简化的例子

#include <iostream>

class B;

class A {
    public:
        B* b;
        int data = 0;

        void changeB(){
            b->data = 5;
        }
};

class B {
    public:
        A* a;
        int data = 0;

        void changeA(){
            a->data = 5;
        }
};

int main(int argc, char const *argv[]) {
    A a;
    B b;

    a.b = &b;
    b.a = &a;

    a.changeB();
    b.changeA();

    std::cout << "a.data: " << a.data << std::endl;
    std::cout << "b.data: " << b.data << std::endl;

    return 0;
}

当我编译这个(Windows 10下的clang++)时,我得到

.\CrossClassAccess.cpp:12:14: error: member access into incomplete type 'B'
            b->data = 5;
             ^
.\CrossClassAccess.cpp:3:7: note: forward declaration of 'B'
class B;
      ^
1 error generated.

在我做了这个简单的例子之后,我想如果我先声明两个类然后定义方法可能会有所帮助。直到某一点,它帮助并显示了预期的解决方案。

#include <iostream>

class B;

class A {
    public:
        B* b;
        int data = 0;

        void changeB();
};

class B {
    public:
        A* a;
        int data = 0;

        void changeA();
};

void A::changeB(){
    b->data = 5;
}

void B::changeA(){
    a->data = 5;
}

// main() is still the same

但我想让这更接近现实,以了解为什么这在我的实际项目中不起作用。所以我把文件分成一个主文件、两个cpp文件和两个头文件。在此之后,它不再起作用了。

CrossClassAccessMain.cpp

#include <iostream>
#include "CrossClassAccessA.hpp"
#include "CrossClassAccessB.hpp"

int main(int argc, char const *argv[]) {
    A a;
    B b;

    a.b = &b;
    b.a = &a;

    a.changeB();
    b.changeA();

    std::cout << "a.data: " << a.data << std::endl;
    std::cout << "b.data: " << b.data << std::endl;

    return 0;
}

CrossClassAccessA.hpp

class B;

class A {
    public:
        B* b;
        int data = 0;

        void changeB();
};

CrossClassAccessB.hpp

class A;

class B {
    public:
        A* a;
        int data = 0;

        void changeA();
};

CrossClassAccessA.cpp

#include "CrossClassAccessA.hpp"

void A::changeB(){
    b->data = 5;
}

CrossClassAccessB.cpp

#include "CrossClassAccessB.hpp"

void B::changeA(){
    a->data = 5;
}

当我编译它时,我再次收到此错误

.\CrossClassAccessA.cpp:4:6: error: member access into incomplete type 'B'
    b->data = 5;
     ^
./CrossClassAccessA.hpp:1:7: note: forward declaration of 'B'
class B;
      ^
1 error generated.
.\CrossClassAccessB.cpp:4:6: error: member access into incomplete type 'A'
    a->data = 5;
     ^
./CrossClassAccessB.hpp:1:7: note: forward declaration of 'A'
class A;
      ^
1 error generated.

我用来编译的命令是

clang++ .\CrossClassAccessMain.cpp .\CrossClassAccessA.cpp .\CrossClassAccessB.cpp

当我更改 CrossClassAccessA 和 CrossClassAccessB 的顺序时,我得到相同的错误只是翻转顺序。
对我来说,看起来一个 cpp 文件是在解析另一个头文件之前编译的。
那么,即使我将代码拆分为不同的文件,我如何才能按照正在运行的示例顺序执行编译过程呢?
对于这个例子,我使用的是 clang++。在我的主要项目中,我使用的是 Arduino,并使用 arduino_debugger.exe 通过命令行对其进行编译。我认为在后端它使用的是 avr-gcc 编译器。我不确定是否可以将编译器标志传递给 arduino_debugger.exe。如果不是(我很确定),我也可以直接使用 avr-gcc 编译它(但它不像使用 arduino_debugger.exe 那样简单)。

标签: c++oopgccclang

解决方案


如果你想使用它们,你需要类的定义,所以你需要在两个文件中包含两个头文件。
由于标题不使用“其他”类,除了名称,这不会是一个问题。


推荐阅读