【问题标题】:C++ nested class/forward declaration issueC++ 嵌套类/前向声明问题
【发布时间】:2010-04-08 13:52:30
【问题描述】:

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

I.E.

class Outer;

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

class Outer
{
 MaybeThisWay x;

 class MaybeThatOtherWay;

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

【问题讨论】:

标签: c++ forward-declaration nested-class


【解决方案1】:

你不能像这样前向声明一个嵌套类。

根据您要执行的操作,也许您可​​以使用命名空间而不是外层的类。你可以前向声明这样的类没问题:

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

【讨论】:

    【解决方案2】:

    如果不完全指定包含类,就无法转发声明嵌套类。不过这个小技巧可以解决问题

    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】:

    没有,但是有什么问题

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

    在这里转发声明没有意义,除非我遗漏了一些东西(这可能是因为你的问题缺乏很多细节)

    请记住,如果一个类是前向声明的,那么您只能声明对前向声明类型的对象的引用或指针。你不能用它做任何其他事情,包括访问它的成员或函数。

    【讨论】:

    • 因为 Inner 没有被提前声明,所以它在那里被完全定义了。
    • 如果你要颠倒这里的部分怎么办。也许公共部分中的某些函数使用私有变量,因此需要声明它们,但 Inner 也需要是私有的。现在我们如何让 Inner 在私有部分可见?
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      如果声明MaybeThatOtherWay 类型的属性,而不是引用或指针,编译器必须知道类的完整定义以确定外部类的大小。因此,无论是不是嵌套类,都不能使用前向声明和那种字段声明。

      【讨论】:

        【解决方案6】:

        如果您只需要一个类型作为函数参数或静态变量,则可以在客户端完成。例如,从 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());
            }
        };
        

        【讨论】:

          猜你喜欢
          • 2023-03-25
          • 2010-10-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多