我最近遇到了这样的情况:

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;

什么好主意吗?


当前回答

我不认为这是一个答案,但这是一个有趣的发现: 如果在名为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;
}

其他回答

如果你真的想避免在头文件中包含讨厌的头文件,你可以这样做:

进行文件:

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

但之后:

您必须在调用时指定嵌入类型(特别是如果您的函数不接受任何嵌入类型的参数) 函数不能是虚函数(因为它是模板)

所以,是的,权衡……

我不认为这是一个答案,但这是一个有趣的发现: 如果在名为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;
}

这将是一种变通方法(至少对于问题中描述的问题-而不是实际问题,即当无法控制C的定义时):

class C_base {
public:
    class D { }; // definition of C::D
    // can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
    class B { };
    C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
    // Danger: Do not redeclare class D here!!
    // Depending on your compiler flags, you may not even get a warning
    // class D { };
    A::B *someField;
};

int main() {
    A a;
    C::D * test = a.someField; // here it can be called C::D
}

你做不到,这是c++语言的漏洞。您必须取消嵌套的类中的至少一个。

如果你可以更改类C和D的源代码,那么你可以分别取出类D,并在类C中输入它的同义词:

class CD {

};

class C {
public:

    using D = CD;

};

class CD;