C++嵌套类/前向声明问题

36

是否可以前向声明一个嵌套类,并将其用作外部类的具体(而不是指针/引用)数据成员的类型?

即:

class Outer;

class Outer::MaybeThisWay   // Error: Outer is undefined
{
};

class Outer
{
 MaybeThisWay x;

 class MaybeThatOtherWay;

 MaybeThatOtherWay y;   // Error: MaybeThatOtherWay is undefined
};

你的代码看起来像是无尽的“Outer包含Outer包含Outer包含Outer…” - Muxecoid
可能是如何前向声明内部类?的重复问题。 - Aaron McDaid
6个回答

40

像这样无法前向声明嵌套类。

根据您尝试做什么,也许您可以在外层使用命名空间而不是类。您可以轻松地前向声明此类:

namespace Outer {
   struct Inner; 
};

Outer::Inner* sweets;  // Outer::Inner is incomplete so 
                       // I can only make a pointer to it
如果您的Outer必须绝对是一个类,并且无法强行将其塞入命名空间中,那么您需要在前置声明Inner的上下文中使Outer成为一个完整的类型。
class Outer
{
   class Inner;  // Inner forward-declared
};  // Outer is fully-defined now

Outer yes;  // Outer is complete, you can make instances of it
Outer::Inner* fun;  // Inner is incomplete, you can only make 
                    // pointers/references to it

class Outer::Inner 
{
};  // now Inner is fully-defined too

Outer::Inner win;  // Now I can make instances of Inner too

15

没有办法在完全不指定外部类的情况下前置声明一个嵌套类。但这个小技巧可以解决这个问题。

class Outer_Inner
{
};

class Outer
{
public:
   typedef Outer_Inner Inner;
};

按照我的命名约定,Outer_Inner 不是一个有效的类名,所以它显然是指一个嵌套类。这对我很有效。

但你仍然不能像这样前向声明嵌套类:

class Outer::Inner;

但至少可以使用前向声明:

class Outer_Inner;

如果你不喜欢Outer_Inner的样式,你可以采用更适合你口味的嵌套类命名约定。 Outer__InnerOuter_nested_Inner等。


3
不要使用双下划线,包含两个下划线的名称被保留给实现以供任何用途。请参见https://dev59.com/KHVC5IYBdhLWcg3woSxW#228797 - villintehaspam
我在这里面临的是同样的问题吗? https://dev59.com/kHnZa4cB1Zd3GeqPr5MS - Julien Guertault

1
如果一个类已经被前向声明(但你还没有完整的定义),那么你只能声明一个指向它的指针,因为编译器还不知道类的大小(也不知道其字段或方法的名称)。

0

如果您只需要将类型作为函数参数或静态变量,可以在客户端上完成。例如,要从Outer接收事件通知:

接口:

class Client {
public:
private:
    static void gotIt(int event);
    class Helper;
};

实现:

#include <outer.hpp>

class Client::Helper {
public:
    static void fromOuter(Outer::Inner const& inner) 
    { 
        gotIt(inner.event());
    }
};

0

不,但是有什么问题吗?

class Outer {
public:  //or protected or private
    class Inner {
    };

private:
    Inner foo;
};

在这里进行前向声明没有意义,除非我漏掉了什么(可能是因为你的问题缺少很多细节)

请记住,如果类被前向声明,则只能声明对前向声明类型对象的引用或指针。您不能对其执行任何其他操作,包括访问其成员或函数。


2
因为 Inner 没有被前向声明,所以它在那里被完全定义。 - CashCow
如果你要反转这里的部分,会怎样呢?也许公共部分中的某些函数使用了私有变量,因此需要声明它们,但是内部部分也需要在私有部分中。现在我们如何允许内部部分在私有部分中可见呢? - Sohaib

0
如果您声明一个类型为MaybeThatOtherWay的属性,而不是引用或指针,则编译器必须知道类的完整定义才能确定外部类的大小。因此,无论是嵌套类还是其他类型的字段声明,您都不能使用前向声明。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接