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

时间:2016-11-28 01:38:23

标签: c++ compiler-errors forward-declaration

我正在尝试用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();
^

我从来没有在课堂上使用过前声明,所以如果我遗漏了一些明显的东西,我会道歉。感谢任何帮助,我提前感谢你。

2 个答案:

答案 0 :(得分:1)

您的代码存在两个问题。

让我们先解决第一个问题。

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

class A {

public:
     void foo();
};

class B {

public:
      void foo();
};

void A::foo()
{
   B b;

   b.foo();
}

void B::foo()
{
   A a;

   a.foo();
};

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

如上所述,你的类A包含一个B类实例,它包含一个A类实例,它包含一个A类实例,它包含一个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 ++对象之间进行类比,只会导致混淆。

答案 1 :(得分:1)

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

#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();
    }