226

私は最近、次のような状況に陥りました。

class A
{
public:
    typedef struct/class {…} B;
…
    C::D *someField;
}

class C
{
public:
    typedef struct/class {…} D;
…
    A::B *someField;
}

通常、クラス名を宣言できます。

class A;

ただし、ネストされた型を前方宣言することはできません。次の場合、コンパイル エラーが発生します。

class C::D;

何か案は?

4

7 に答える 7

254

それはできません。C++ 言語の穴です。ネストされたクラスの少なくとも 1 つのネストを解除する必要があります。

于 2009-06-04T15:23:10.313 に答える
38
class IDontControl
{
    class Nested
    {
        Nested(int i);
    };
};

次のような前方参照が必要でした。

class IDontControl::Nested; // But this doesn't work.

私の回避策は次のとおりです。

class IDontControl_Nested; // Forward reference to distinct name.

後で完全な定義を使用できるようになったとき:

#include <idontcontrol.h>

// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
    // Needed to make a forwarding constructor here
    IDontControl_Nested(int i) : Nested(i) { }
};

複雑なコンストラクターや、スムーズに継承されないその他の特別なメンバー関数が存在する場合、この手法は価値がある以上に面倒なことになるでしょう。特定のテンプレート マジックの反応が悪くなることは想像できました。

しかし、私の非常に単純なケースでは、うまくいくようです。

于 2011-11-07T01:22:23.130 に答える
5

ヘッダー ファイルに厄介なヘッダー ファイルを #include することを本当に避けたい場合は、次のようにします。

hpp ファイル:

class MyClass
{
public:
    template<typename ThrowAway>
    void doesStuff();
};

cpp ファイル

#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"

template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
    // ...
}

しかしその後:

  1. 呼び出し時に埋め込み型を指定する必要があります (特に、関数が埋め込み型のパラメーターを取らない場合)。
  2. 関数を仮想にすることはできません (テンプレートであるため)

だから、ええ、トレードオフ...

于 2012-04-16T12:56:30.987 に答える
1

私はこれを答えとは呼びませんが、それでも興味深い発見: C という名前空間で構造体の宣言を繰り返すと、(少なくとも gcc では) すべて問題ありません。C のクラス定義が見つかると、名前空間 C を黙って上書きするようです。

namespace C {
    typedef struct {} D;
}

class A
{
public:
 typedef struct/class {...} B;
...
C::D *someField;
}

class C
{
public:
   typedef struct/class {...} D;
...
   A::B *someField;
}
于 2009-06-04T15:48:03.347 に答える
0

これは、外側のクラスを名前空間として前方宣言することによって実行できます。

サンプル: ネストされたクラス others::A::Nested を、others_a.h で使用する必要がありますが、これは制御できません。

その他_a.h

namespace others {
struct A {
    struct Nested {
        Nested(int i) :i(i) {}
        int i{};
        void print() const { std::cout << i << std::endl; }
    };
};
}

my_class.h

#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif

class MyClass {
public:
    MyClass(int i);
    ~MyClass();
    void print() const;
private:
    std::unique_ptr<others::A::Nested> _aNested;
};

my_class.cpp

#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"

MyClass::MyClass(int i) :
    _aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
    _aNested->print();
}
于 2018-05-31T07:46:28.953 に答える