1

我知道我们不能定义以不完整类型作为参数的函数,因此预计以下代码无法编译并出现错误 C2027: use of undefined type '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;
};

我们在定义类时拥有的不完整类类型与前向声明暴露的不完整类型之间有区别吗?

4

1 回答 1

3

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

该语言在 8.3.5/6 (C++03) 中对这种情况进行了特殊处理

函数定义的参数类型或返回类型不应是不完整的类类型(可能是 cv 限定的),除非函数定义嵌套在该类的成员规范中(包括在该类中定义的嵌套类中的定义) )。

这条规则可以被看作是另一个类似规则的“卫星”——这条规则表示类类型总是从类成员函数、默认参数和构造函数初始化列表的主体中完整地看到(并且作为完整类型)。见 9.2/2 (C++03)

在类说明符的结束 } 处,类被认为是完全定义的对象类型(3.9)(或完整类型)。在类成员规范中,类在函数体、默认参数和构造函数 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`
    {}
};
于 2013-07-11T04:47:17.923 回答