在 C++ 中使用前向声明的错误

Errors using forward declaration in c++

我正在尝试用 c++ 编写一个简单的程序,我有 2 个 类,两者都可以相互访问函数。这是我最终实际尝试做的事情的简化,即创建一个棋盘游戏 类。我能够在 java 中做到这一点,但我现在 运行 遇到了问题,试图在 C++ 中做同样的事情。我的代码如下:

#include <iostream>
class B;
class A {
    public:
            void sync(B obj){
                    b = obj;
            }
            void print(){
                    std::cout << "Hello from class A" << std::endl;
            }
            void printBoth(){
                    std::cout << "Hello from class A" << std::endl;
                    b.print();
            }
    private:
            B b;
};

class B {
    public:
            B(A obj){
                    a = obj;
            }
            void print(){
                    std::cout << "Hello from class B" << std::endl;
            }
            void printBoth(){
                    std::cout << "Hello from class B" << std::endl;
                    a.print();
            }
    private:
            A a;
};

int main(){
    A a;
    B b(a);
    a.sync(b);
    a.printBoth();
    std::cout << std::endl;
    b.printBoth();
    return 0;
}

当我尝试用 g++ example.cpp 编译它时,我收到 5 个错误:

example.cpp:20:5: error: field ‘b’ has incomplete type
B b;
 ^
example.cpp: In member function ‘void A::sync(B)’:
example.cpp:7:8: error: ‘obj’ has incomplete type
void sync(B obj){
    ^
example.cpp:3:7: error: forward declaration of ‘class B’
class B;
   ^
example.cpp:8:4: error: ‘b’ was not declared in this scope
b = obj;
^
example.cpp: In member function ‘void A::printBoth()’:
example.cpp:17:4: error: ‘b’ was not declared in this scope
b.print();
^

我从未在 类 中使用过前向声明,所以如果我遗漏了一些明显的东西,我深表歉意。感谢您的帮助,在此先感谢您。

你的代码有两个问题。

我们来看第一个问题。

下面是两个 class 具有相互调用方法的示例。毫无意义,并导致无限循环,但这演示了前向声明的一般原则,您可以将其用作模板来修复您显示的代码。

class A {

public:
     void foo();
};

class B {

public:
      void foo();
};

void A::foo()
{
   B b;

   b.foo();
}

void B::foo()
{
   A a;

   a.foo();
};

现在,您的代码存在第二个问题:

正如所写,您的 class A 包含 class B 的实例,其中包含 class A 的实例,其中包含 class A 的实例,其中包含 class B 的一个实例,一直到宇宙在一个巨大的黑洞中内爆。可以说,这不会编译。

C++ 对象从根本上不同于 Java 对象。他们以完全不同的方式工作。您可以在 Java 中执行此操作,因为肮脏的小秘密是 Java 中的所有对象实际上都是海市蜃楼,它们实际上是指向实际对象的引用计数指针。在 C++ 中,最接近的等效项是向对象声明一个 std::shared_ptr

#include <memory>

class A;
class B;

class A {

  // ...

  private:
            std::shared_ptr<B> b;
};

class B {

  // ...

  private:
            std:shared_ptr<A> a;
};

这将是您显示的代码的第二个问题。通常,在学习 C++ 对象时,您需要几乎忘记所有关于 Java 对象的知识。它们本质上是不同的,并且尝试在您已经了解的 Java 对象和 C++ 对象之间始终如一地进行类比只会导致混淆。

您可以随时尝试重新设计,即:

#include <iostream>
#include "A.hpp"

int main(){
    A a;
    B b(a);
    a.sync(b);
    a.printBoth();
    std::cout << std::endl;
    b.printBoth();
    return 0;
}

B.hpp:

class A;

class B {
    public:
            B() {}
            B(A obj);
            void print();
            void printBoth();
    private:
            A* a;
};

B.cpp:

#include <iostream>
#include "A.hpp"

            B::B(A obj){                                                                    
                    a = new A(obj);                                                         
            }                                                                               
            void B::print(){                                                                
                    std::cout << "Hello from class B" << std::endl;                         
            }                                                                               
            void B::printBoth(){                                                            
                    std::cout << "Hello from class B" << std::endl;                         
                    a->print();                                                             
            } 

A.hpp:

#include "B.hpp"

class A {
    public:
            void sync(B obj);
            void print();
            void printBoth();
    private:
            B b;
};

A.cpp:

#include <iostream>
#include "A.hpp"
    void A::sync(B obj){
              b = obj;
    }
    void A::print(){
      std::cout << "Hello from class A" << std::endl;
    }
    void A::printBoth(){
      std::cout << "Hello from class A" << std::endl;
      b.print();
    }