【问题标题】:Why an inline declaration is not an incomplete type?为什么内联声明不是不完整的类型?
【发布时间】:2015-12-17 13:38:55
【问题描述】:

考虑下面的代码:

struct Foo {
    struct Bar;
    Foo()
    {
        Bar bar; // Why isn't Bar an incomplete type?!
    }
    struct Bar {}; // Full definition
};

// struct Bar {}; // fails to compile due to incomplete type

int main()
{
    Foo foo;
}

它在至少 2 个编译器(gcc5.2、clang3.5)下编译得很好。我的问题是:

  • 为什么Bar 在构造函数Foo::Foo 中不被视为不完整类型,因为我在构造函数上方将其前向声明但在构造函数内部完全使用它?

每当我将Foo::Bar 移出班级,换句话说Bar 成为一个独立班级时,我都会得到预期的

错误:聚合 'Foo::Bar bar' 的类型不完整,无法定义

【问题讨论】:

  • 成员函数体的行为就好像它们是在外线定义的(即,在类定义之后)。
  • 主要原因是编译器在确定如何处理每种类型时,可以对类内的所有定义进行本地搜索。范围被全面检查,因为它只是程序的一小部分,它不需要依赖源代码中的声明顺序。

标签: c++ incomplete-type


【解决方案1】:

在成员规范中,类在函数体内被认为是完整的,来自 C++ 标准部分草案9.2[class.mem]

一个类被认为是一个完全定义的对象类型(3.9)(或 完整类型)在类说明符的结束 } 处。 内 类成员规范,类被认为是完整的 函数体,默认参数,使用声明引入 继承构造函数 (12.9)、异常规范和 非静态数据成员(包括 嵌套类中的此类内容)。否则视为不完整 在它自己的类成员规范中

这意味着您甚至不必转发声明Bar (see it live):

struct Foo {
    Foo()
    {
        Bar bar; 
    }
    struct Bar {};  
};

前向声明可能有助于避免违反3.3.7 paragraph 2 and 3 部分。

【讨论】:

  • 谢谢!关于您的最新编辑,似乎每当内部类具有不同的访问说明符时,我都必须转发声明。参见例如this,如果我删除前向声明,代码将无法编译(尝试使用 gcc 和 clang)。
  • @vsoftco 对,在这种特定情况下,它确实可以在没有前向声明的情况下工作,因为这不是我上面引用的段落所定义的类被认为是完整的地方之一。
猜你喜欢
  • 2018-07-16
  • 2013-09-15
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 2013-11-11
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多