17

相互へのポインターを使用して、2 つの同一のクラス X と Y を作成しました。以下の Xh のコードを参照してください。Yh は、すべての X と Y を交換したものと同じです。ただし、このコードでは Connect メソッドでエラーが発生します (エラー C2027: 未定義の型 'Y' の使用)。Xh では、クラス Y を前方宣言しましたが、Y に SetXPointer という名前のメソッドがあることを認識していません。したがって、このメソッドも前方宣言する必要がありますよね?

これを実行しようとすると (class Y; という行の下に Y::SetXPointer(X* pX_in); という行を追加すると)、コンパイラ エラー C2761: 'void Y::SetXPointer(X *)' : member function redeclaration が発生します。禁止されている。クラスXでクラスYのパブリックメソッドを使用する方法はありますか?

// X.h

#pragma once

#include "Y.h"

// Forward declaration
class Y;

class X
{
public:
    X(void) : data(24) {};
    ~X(void) {};
    int GetData() { return data; }
    void SetYPointer(Y* pY_in) { pY = pY_in; }
    Y* GetYPointer() { return pY; }
    void Connect(Y* Y_in) { pY = Y_in; Y_in->SetXPointer(this); }
private:
    int data;
    Y *pY;
};
4

4 に答える 4

21

クラス本体にメソッド本体を含めないでください。両方のクラスを作成し、両方のクラスが完成したら、メソッドの実装を作成します。

class Y;
class X {
  …
  void Connect(Y* Y_in);
  …
};
class Y {
  …
  void Connect(X* X_in);
  …
};
inline void X::Connect(Y* Y_in) {
  pY = Y_in;
  Y_in->SetXPointer(this);
}
inline void Y::Connect(X* X_in) {
  pX = X_in;
  X_in->SetXPointer(this);
}

Connectこのようにして、メソッドが実装されるまでに、クラスのオブジェクトがメモリ内でどのように配置されるかについての完全な情報が利用可能になります。また、クラス本体のメソッドと宣言inlineされたメソッドはどちらも同じ方法でインライン化されるため、パフォーマンスも同じになります。

唯一の欠点は、合理的な方法でこれら 2 つのクラスを 2 つのヘッダーに分割できないことです。

于 2012-07-05T12:25:36.673 に答える
4

これを行う唯一の方法は、両方のクラスのメソッドに完全な型が必要な場合、実装を実装ファイルに分離することです。

于 2012-07-05T12:19:18.493 に答える
3

クラスBをクラスAに配置できます

using namespace std;

class A
{
        public:
        void run()
        {
                B b("hi");
                b.run(this);
        }

        void print(string &msg) { cout << msg << endl; }

        private:
        class B
        {
                public:
                B(string m) : msg(m) {}
                void run(A *a) { a->print(msg); }

                private:
                string msg;
        };
};

int main()
{
        A a;
        a.run();
        return 0;
}
于 2014-01-20T18:46:14.900 に答える
2

X と Y の間で実装の大部分を共有する場合は、テンプレートを使用して共有することをお勧めします。一例を以下に示します。

template<bool isX> class XY
{
public:
  typedef XY<!isX> YX; // This is the opposite type to the current one.
  XY(void) : data(24) {};
  ~XY(void) {};
  int GetData() { return data; }
  void SetPointer(YX* pYX_in) { pYX = pYX_in; }
  YX* GetPointer() { return pYX; }
  void Connect(YX* YX_in) { pYX = YX_in; YX_in->SetPointer(this); }
private:
  int data;
  YX *pYX;
};

typedef XY<true> X;
typedef XY<false> Y;

テンプレートメソッドは使用時にのみインスタンス化されるため、インスタンス化されるまでに両方のタイプが認識されるため、上記の問題を回避できます。X後で と の間に違いがYある場合は、 の代わりに継承を使用できますtypedef

于 2012-07-05T12:31:59.510 に答える