1

ここからの情報を使用してクラス間で情報を共有しようとしていますが、これら2つのクラスをコンパイルして、相互に通信することができません。

したがって、私が欲しいのは、ClassBへの参照を取得しClassAClassBで初期化することClassAです。

コンパイラエラー(g ++を使用):

メンバー関数内'void ClassA::foo()'
hello.cpp:9:エラー:'ClassB'このスコープで宣言されていません
hello.cpp:9:エラー:'someB'このスコープで宣言されていませんhello.cpp:9:エラー: hello.cpp:9
の前に型指定子が必要です'ClassB'
:エラー:';'前に予想'ClassB'

class ClassB;だから私は前に追加してみますClassA

お気に入り:

class ClassB; // just this here.

class ClassA; // all of classA here.

class ClassB; // all of classB here.

そして私は得る:

hello.cpp:メンバー関数内'void ClassA :: foo()':
hello.cpp:11:エラー:不完全な型の無効な使用' struct
ClassB'hello.cpp:3:エラー:' structClassB'helloの前方
宣言.cpp:12:エラー:不完全な型'structClassB'の無効な使用
hello.cpp:3:エラー:'structClassB'の前方宣言


これは、上記のWebサイトに基づいて使用しようとしているコードです。

include stdio.h

class ClassA {
    public:
        void foo() {
            ClassB *someB = new ClassB();
            someB->setRelative(this);
        }

        void bar() {
            printf("B is communicating with me =)\n");
        }
};

class ClassB {

    ClassA *m_relative;

    public:
        void setRelative(ClassA *other) {
            this->m_relative = other;
        }

        void foo() {
            m_relative->bar();
        }
};
4

3 に答える 3

3

ここでは明らかに循環依存関係があります。これは、ヘッダーだけを使用して実際に解決することはできません(一部のマクロトリックで可能かもしれませんが、心配する必要はありません)。

あなたがすべきことは、コードを宣言(ヘッダー)と実装に分割することです。

ああ

// only include this file once per translation unit
#pragma once

// tell the compiler B is going to be a class,
// so B* is a pointer to a class - nothing more is needed for now.
class B;

// full declaration of A
class A {
    B *child;

public:
    A(void);
}

a.cpp

#include "a.h" // included whenever the structure/size of A has to be known
#include "b.h" // same for B

A::A(void) : child(new B(this)) {
    // do something with child or...
    B * = new B(this);
}

bh

// only include this file once per translation unit
#pragma once

// again, just tell the compiler A is going to be a class
class A;

class B {
    A *parent;
public:
    B(A *pparent);
}

b.cpp

#include "a.h"
#include "b.h"

B::B(A *pparent) : parent(pparent) {
    // do something with parent
}
于 2012-12-29T16:56:54.130 に答える
1

この質問のように 各クラス(AとB)には、ヘッダーファイルと実装ファイルが必要です。

各ヘッダーファイル(例:Ah)には、他のヘッダーファイル(例:Bh)を含めることはできませんが、他のクラスへの順方向参照(例:クラスB;などのステートメント)を含めることができます。その後、ポインターや他のクラスへの参照を使用できます。宣言内のクラス(たとえば、クラスAにはデータメンバーおよび/またはメソッドパラメーターとしてB *が含まれる場合があります)。

各CPPファイル(A.cppなど)には、複数のヘッダーファイル(AhとBhなど)を含めることができます。各CPPファイルには、最初に独自のヘッダーファイルを含めることをお勧めします(たとえば、A.cppにはAh、次にBhを含める必要がありますが、B.cppにはBh、次にAhを含める必要があります)。

各ヘッダーファイルには、クラスの定義ではなく、宣言のみが含まれている必要があります。たとえば、クラスのメソッドの署名はリストされますが、メソッド本体/実装はリストされません(メソッド本体/実装は.cppファイルに含まれます)。 、ヘッダーファイルにはありません)。ヘッダーファイルには実装の詳細が含まれていないため、他のクラスの詳細に依存しません(表示する必要はありません)。せいぜい、彼らは、たとえば、Bがクラスの名前であることを知る必要があります。これは、別のヘッダーファイルにヘッダーファイルをインクルードする代わりに、フォワード宣言から取得できます。

例えば:

//ああクラスB; //前方宣言

lass A {
   void foo(B* b); // pointers and references to forward-declared classes are ok
};


// b.h
Class A; // forward declaration

Class B {
   void bar(A& a); // pointers and references to forward-declared classes are ok
};


// a.cpp
#include "a.h"
#include "b.h"

void A::foo(B* b) {
   b->bar(*this); // full declaration of B visible, ok to call members now
}


// b.cpp
#include "a.h"
#include "b.h"

void B::bar(A& a) {
   a.foo(this); // full declaration of A visible, ok to call members now
}
于 2012-12-29T16:56:34.057 に答える
0

class Aclass Bそれを作成して呼び出すには、の完全な定義が必要someB->setRelative(this)です。 を呼び出すにclass Bは、の完全な定義が必要です。つまり、これは一種の鶏が先か卵が先かという問題です。class Am_relative->bar()

この円を壊すには、ヘッダーファイルのクラスとメソッドの宣言とcppファイルのメソッド定義を分割する必要があります。

于 2012-12-29T17:01:39.937 に答える