不完整类型:定义与前向声明之前的类用法

时间:2013-07-11 04:40:39

标签: c++ incomplete-type

我知道我们无法定义将不完整类型作为参数的函数,因此预计下面的代码无法使用错误编译C2027:使用未定义类型'Derived'

class Derived;
class Base{
public:
   void test(Derived d){ cout<<"test"<<endl; }
};
class Derived : public Base{
   int j;
};

通过相同的逻辑,当test()接受Base的对象时,我希望编译失败,这个对象在此之前是不完整类型的。但是,它没有,并且以下代码编译良好

class Derived;
class Base{
public:
    void test(Base b){ cout<<"test"<<endl; }
};
class Derived : public Base{
    int j;
};

在定义类时我们拥有的不完整类类型与前向声明公开的不完整类型之间是否存在差异?

1 个答案:

答案 0 :(得分:3)

逻辑不一样。不同之处在于,在第二个示例中,函数Base::test()使用其自己的类Base的对象(而不是完全外来的类Derived)。

该语言在8.3.5 / 6(C ++ 03)

中对这种情况给予特殊处理
  

函数定义的参数类型或返回类型   除非是,否则不应是不完整的类型(可能是cv认证的)   函数定义嵌套在member-specification中   该类(包括在。中定义的嵌套类中的定义)   类)。

此规则可被视为&#34;卫星&#34;对于另一个类似的规则 - 表示类类型总是在类成员函数,默认参数和构造函数初始化列表的主体中完整地看到(并且作为完整类型)。见9.2 / 2(C ++ 03)

  

在结束时,类被视为完全定义的对象类型(3.9)(或完整类型)   类说明符。在类成员规范中,该类在函数内被视为完整   body,默认参数和构造函数ctor-initializers(包括嵌套类中的这些东西)。除此以外   它在自己的类成员规范中被认为是不完整的。

请注意,在结束}之前的所有其他上下文中,该类被视为不完整

struct S {
  S foo(S s) // <- OK, due to 8.3.5/6
    { return s; } 

  void bar(int a = sizeof(S)) // <- OK, due to 9.2/2
    { S s; } // <- OK, due to 9.2/2

  int (*baz())[sizeof(S)] // <- ERROR: incomplete type in `sizeof`
    { return NULL; }

  void qux(int a[sizeof(S)]) // <- ERROR: incomplete type in `sizeof`
    {}
};