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 はクラス A をまだ ah で宣言していないため、このコードはエラーを発生させます。

では、A のインスタンスを B に渡すにはどうすればよいでしょうか。

4

3 に答える 3

4

必要がある

  1. コンストラクターの値渡しパラメーターBをポインターまたは参照に変更します*
  2. の定義をB::Bcpp ファイルに移動します (これにより、 の定義への直接的な依存関係が削除されA
  3. ABh で前方宣言:

    // 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.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
}
于 2012-04-25T14:18:51.543 に答える
0

構文を使用してクラスを前方宣言します

class A;

あなたの bh ファイルでは、これは、参照を持つ A というクラスがあることをコンパイラに伝えるのに十分です。そのクラスの内部にアクセスすることはできませんが (たとえば、クラスのメンバーやサイズを教えていません)、ポインターまたは参照として使用するには十分です。

他にできることは、設計を調べて、そのような循環依存を削除することです。

于 2012-04-25T14:21:11.870 に答える