C ++:由于#include循环,无法将对象实例传递给另一个类

时间:2012-04-25 14:17:17

标签: c++ class include

假设我有2个分类:

// a.h
#ifndef A_H
#define A_H

#include "b.h"

class A {
  public: void a() {
    B* b = new B(this);
  }
}

#endif


// b.h
#ifndef B_H
#define B_H

#include "a.h"

class B {
  public: B(A* a) {
     // ...
  }
}

#endif

此代码将引发错误A has not been declared,因为类A引用了类B,而类B又引用了尚未在a.h中声明的类A.

那么如何将A的实例传递给B?

3 个答案:

答案 0 :(得分:4)

你需要

  1. B构造函数的pass-by-value参数更改为指针或引用*
  2. B::B的定义移至cpp文件(这将删除对A定义的任何直接依赖,并允许您
  3. 在B.h中
  4. 转发声明 A

    // b.h
    #ifndef B_H
    #define B_H
    
    class A;
    
    class B {
      public: B(const A& a) {
         // ...
      }
    }
    
    #endif
    
    // b.cpp
    
    #include "b.h"
    #include "a.h"
    
    public B::B(const A& a) {
      // ...
    }
    
  5. 请注意,我为const构造函数参数添加了A&限定符,因为我假设您不想在a的构造函数中修改B。 / p>

    当然,您也可以通过将A::a的定义和相应的#include "b.h"移动到a.cpp中来反过来播放。

    * 无论如何你最有可能这样做,因为你不太可能想要按值传递A对象。按值传递对象意味着隐式创建对象的副本并将其推送到堆栈。哪个

    • 表示对参数对象所做的更改不会影响原始对象,这通常不是您想要的,因此是错误的来源,
    • 包括创建和销毁临时
    • 通常比参考/指针消耗更多的内存,
    • 打开了object slicing错误的大门。

答案 1 :(得分:1)

您将实现移到单独的文件中。这样您就不必在B.h中包含A.h

// a.h
class A {
public: 
    void a();
};

// b.h
#include "a.h"
class B {
public: 
    B(A a) { }
};

// a.cpp
#include "a.h"
#include "b.h"
void A::a(){
    B* b = new B(*this); //B constructor doesn't take a pointer
}

答案 2 :(得分:0)

使用语法

向前声明一个类
class A;
在你的b.h文件中,这足以告诉编译器有一个名为A的类,你将引用它。它不允许你访问该类的内部(例如,你没有告诉它它有什么成员,或它有多大),但它足以用作指针或引用。

您可以做的另一件事是查看您的设计并尝试删除此类循环依赖项。