在C++中转发嵌套类型/类的声明

Cal*_*ius 189 c++ nested class forward-declaration

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

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

class C
{
public:
    typedef struct/class {...} D;
...
    A::B *someField;
}
Run Code Online (Sandbox Code Playgroud)

通常你可以声明一个类名:

class A;
Run Code Online (Sandbox Code Playgroud)

但是你不能转发声明一个嵌套类型,以下导致编译错误.

class C::D;
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Ada*_*eld 218

你不能这样做,这是C++语言的一个漏洞.您必须取消嵌套至少一个嵌套类.

  • 哦.正是我不希望谷歌出现.无论如何,谢谢你的简明回答. (60认同)
  • 同样在这里...有人知道*为什么*这是不可能的?似乎存在有效的用例,这种缺陷会在某些情况下阻止架构的一致性. (19认同)
  • 谢谢你的回答.就我而言,它们不是我的嵌套类.我希望通过一些前向引用来避免巨大的库头文件依赖.我想知道C++ 11是否修复了它? (6认同)
  • 每当我在这种语言中遇到如此不必要的缺陷时,我就会在笑和哭之间挣扎 (2认同)

Mar*_*Ray 32

class IDontControl
{
    class Nested
    {
        Nested(int i);
    };
};
Run Code Online (Sandbox Code Playgroud)

我需要一个前向引用,如:

class IDontControl::Nested; // But this doesn't work.
Run Code Online (Sandbox Code Playgroud)

我的解决方法是:

class IDontControl_Nested; // Forward reference to distinct name.
Run Code Online (Sandbox Code Playgroud)

后来我可以使用完整的定义:

#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) { }
};
Run Code Online (Sandbox Code Playgroud)

如果有复杂的构造函数或其他特殊成员函数没有顺利继承,那么这种技术可能会比它的价值更麻烦.我可以想象某些模板魔法反应很糟糕.

但在我非常简单的情况下,似乎有效.

  • 在C++ 11可以通过使用`基本名::基名继承构造;在派生类,因此,没有复杂的构建函数问题`. (15认同)

小智 5

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

hpp文件:

class MyClass
{
public:
    template<typename ThrowAway>
    void doesStuff();
};
Run Code Online (Sandbox Code Playgroud)

.cpp文件

class MyClass
{
public:
    template<typename ThrowAway>
    void doesStuff();
};
Run Code Online (Sandbox Code Playgroud)

但是之后:

  1. 您必须在调用时指定嵌入类型(特别是如果您的函数不采用嵌入类型的任何参数)
  2. 你的函数不能是虚拟的(因为它是一个模板)

所以,是的,权衡...

  • 大声笑,在 C++ 项目中使用 **.hpp** 头文件将其与通常以 .h 结尾的 C 头文件区分开来。当在同一个项目中使用 C++ 和 C 时,有些人更喜欢 C++ 文件的 .hpp 和 .cpp,以明确他们处理的文件类型,以及 C 文件的 .h 和 .c。 (8认同)