1

假设我有 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 类又引用了尚未在 ah 中声明的 A 类。

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

4

3 回答 3

4

你需要

  1. B构造函数的传值参数改为指针或引用*
  2. 将 的定义移动B::B到 cpp 文件(这消除了对 的定义的任何直接依赖A,并允许您
  3. A在 Bh 中前向声明:

    // 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) {
      // ...
    }
    

请注意,我const为构造函数参数添加了一个限定符A&,因为我假设您不想aB.

当然,你也可以反其道而行之,A::a把和对应的定义#include "b.h"移到 a.cpp 中。

*无论如何,您很可能应该这样做,因为您不太可能希望在A那里按值传递对象。按值传递对象意味着隐式创建对象的副本并将其压入堆栈。哪一个

  • 意味着对参数对象所做的更改不会影响原始对象,这通常不是您想要的,因此是错误的来源,
  • 包括创建和销毁临时文件,
  • 通常比引用/指针消耗更多的内存,
  • 打开对象切片错误的大门。
于 2012-04-25T14:20:35.913 回答
1

您将实现移动到单独的文件中。这样你就不必包括B.hinside 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
}
于 2012-04-25T14:18:51.543 回答
0

您使用语法向前声明一个类

class A;

在您的 bh 文件中,这足以告诉编译器您将引用一个名为 A 的类。它不允许您访问该类的内部(例如,您没有告诉它它有哪些成员,或者它有多大),但它足以用作指针或引用。

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

于 2012-04-25T14:21:11.870 回答