为什么类可以在成员函数定义中使用,但在用作成员时被视为不完整

Why can a class be used within itself in member function definition, but is regarded as incomplete when used as a member?

本文关键字:成员 函数 定义 为什么      更新时间:2023-10-16
class A
{
     private:
        A a;
};

为什么类中的 A 是不完整的类型?

class A
{
     public:
          A& operator= (A a){return *this;}
};

operator=的参数A不是不完整的类型吗?为什么上面的代码会编译?

因为在类定义中的开放空间中使用A与在成员函数定义的参数列表中使用它之间存在差异。这是两个不同的范围。

[C++11: 9.2/2]: 类在类说明符的结束}被视为完全定义的对象类型 (3.9((或完整类型(。在类成员规范中,类在函数体、默认参数、异常规范和非静态数据成员(包括嵌套类中的此类内容(的大括号或等于初始值设定项中被视为完整的。否则,它在其自己的类成员规范中被视为不完整。

然后是以下特殊情况:

[C++11: 8.3.5/9]:类型不得在返回或参数类型中定义。参数的类型或函数定义的返回类型不应是不完整的类类型(可能是 cv 限定的(,除非函数定义嵌套在该类的成员规范中(包括类中定义的嵌套类中的定义(。

">

原来如此。">

实际上,很明显不可能在A中存储A(因为这需要无限封装(,而在成员函数的参数列表中显然并非如此。因此,标准委员会有机会让我们更容易一点,他们抓住了它。

此外,如果您尝试在函数的定义中使用 a 的成员,那么这也是允许的(根据上面的第一个引号(,就好像该函数是在类定义结束后以词法方式声明的一样。

在一般情况下,第一个块是不可能的,因为要知道sizeof(A)是什么(对于类(,它需要知道sizeof(A)是什么(对于成员(。

第二种情况的不同之处在于,即使成员函数的定义在语法上在类内部,语言也会认为该定义在类之外。 编译器将翻译该代码,就像您键入它一样:

class A {
public:
   A& operator=(A a);
};
inline A& A::operator=(A a) { return *this; }

声明函数接受或返回不完整类型的对象是合法的。 当类型真正被使用时,在类之外的函数定义中,类型已经完成,所以它也完全没问题。

看待这个问题的方法是了解如果这实际上是合法的会发生什么。实例化类时,首先构造其所有类成员。因此,在您的示例中,A a的构造将在 A 完全构造之前进行,这是不可能的。

此外,这将导致 A 对象的无限递归构造。

第二个是编译,因为你只使用A的引用而不是A的对象。但是在第一种情况下,您需要 A 的对象,因此需要完整的类型,这只能在关闭 } 后发生