【问题标题】:Nested class definition outside outer class's, while outer class contains instance of inner class外部类的嵌套类定义,而外部类包含内部类的实例
【发布时间】:2013-11-21 00:20:07
【问题描述】:

C++

如何将内部(嵌套)类的定义放在其外部(封闭)类的定义之外,其中外部类至少有一个内部类的实例作为数据成员?我进行了搜索,但我找到的最相关的 SO 答案 Nested Class Definition in source file 没有外部类具有内部对象作为数据成员的示例。我遵循了这个答案,就在外部类的定义中声明但不定义内部类而言,但我的代码仍然被破坏:

struct Outer
{
    struct Inner;
    Inner myinner;
    Outer() : myinner(2) {}
};

struct Outer::Inner
{
    Inner(int n) : num(n) {}
    int num;
};

int main()
{
    Outer myouter;
}

它在 VC11 中给出错误error C2079: 'Outer::myinner' uses undefined struct 'Outer::Inner'。

为什么损坏的代码没有与在Outer 的定义中定义Inner 的版本等效的效果,就像在下面的工作代码中一样?

struct Outer
{
    struct Inner
    {
        Inner(int n) : num(n) {}
        int num;
    } myinner;
    Outer() : myinner(2) {}
};

【问题讨论】:

    标签: c++ nested inner-classes nested-class outer-classes


    【解决方案1】:

    这是一个危险信号,但您可以使用假模板来做到这一点。

    template< typename = void >
    struct Outer_temp
    {
        struct Inner;
        Inner myinner;
        Outer_temp() : myinner(2) {}
    };
    
    typedef Outer_temp<> Outer; // Hide template from user.
    
    template< typename v >
    struct Outer_temp< v >::Inner
    {
        Inner(int n) : num(n) {}
        int num;
    };
    
    int main()
    {
        Outer myouter;
    }
    

    模板内的Inner 是一个依赖类型,因此在定义实例、成员或任何其他上下文时,它不需要是完整的。它只需要在实例化发生后完成,在本例中来自main。

    我想不出这样做的充分理由,但就是这样。

    不应为了程序组织而使用嵌套类。嵌套暗示了一种概念依赖,“内部不能存在,除非在外部提供的上下文中”。例如,虽然容器节点类嵌套在容器中很常见,但这可能会导致问题。 SCARY 成语是一种拒绝这种组织并获得改进的通用性的设计风格。

    TL;DR:独立定义两个类,并用嵌套的typedef 链接它们。

    【讨论】:

    • +1 用于工作代码。我了解您的模板语法。但我不知道为什么它适用于您的假模板,但不适用于我的非模板。不能说我是模板专家。 "Inner inside the template is a dependent type, so it does not need to be complete as you define an instance, in a member or any other context. It only needs to be complete once the instantiation happens” 你的意思是我的Inner 是一个独立的类型并且在Outer 中被实例化时是不完整的?
    • @CodeBricks “依赖”是指依赖于模板的参数。 “什么是内在?这取决于这是什么专业。”模板可以使用在其自身之后声明的类型来实例化,因为模板可以引用不完整的类型等,只要它们依赖于参数。我引入了这样一个错误的依赖项,将Inner myinner 的编译推迟到main。
    • 为什么我的代码中Inner 的声明不能将编译推迟到Outer 在Inner 的定义下面看到Outer 的定义?它似乎适用于常规功能。示例:void g(); void f(){g();} void(g){cout&lt;&lt;"hi\n";}
    • @CodeBricks 你可以调用一个只有声明的函数,没有定义。在定义类之前,您不能实例化它。如果您在Outer 内使用Inner *myinner,则永远不会发生问题,因为定义指针不需要定义。但是指针算术++myinner 需要一个定义。只是有很多规则:P
    • 在您的回答中,“独立定义两个类并将它们与嵌套的typedef 链接”是什么意思?你的意思是:struct Outer { /*...*/ typedef Inner itd; /*...*/}; struct Inner {/*...*/};?如果是这样,那为什么?如果您希望Inner 在Outer 之外不存在,这如何帮助Inner 在Outer 之外或多或少地被访问?对Inner 的成员的可访问性是否仅取决于Inner 的访问修饰符,而不管哪个类将其实例用作数据成员?或者你不是故意把“嵌套”这个词放在那里吗?您只是指上面的代码吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 2014-10-30
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    相关资源
    最近更新 更多