class A
{
private:
A a;
};
为什么课堂上的A是不完整的类型?
class A
{
public:
A& operator= (A a){return *this;}
};
A
的参数operator=
不是不完整的类型吗?上面的代码为什么要编译?
答案 0 :(得分:4)
因为在类定义中在开放空间中使用A
并在成员函数定义的参数列表中使用它之间存在差异。这是两个不同的范围。
[C++11: 9.2/2]:
在类说明符的结束}
,类被视为完全定义的对象类型(3.9)(或完整类型)。在类 member-specification 中,该类在函数体,默认参数,异常规范和大括号或等于初始化中被认为是非完整的非静态类数据成员(包括嵌套类中的这类内容)。 否则在其自己的类成员规范中被视为不完整。
然后是以下特例:
[C++11: 8.3.5/9]
:不应在返回或参数类型中定义类型。 函数定义的参数类型或返回类型不应是不完整的类类型(可能是cv-qualified),除非函数定义嵌套在该类的成员规范 (包括在类中定义的嵌套类中的定义)。
"这就是它的方式。"
实际上,很明显,将A
存储在A
内是不可能的(因为这需要无限封装),而事实上并非如此。成员函数的参数列表。所以标准委员会有机会让我们更轻松一点,他们就接受了。
此外,如果您尝试在函数定义中使用a
的成员,那么也允许(根据上面的第一个引用),如果函数是在类定义结束后以词法方式声明的。
答案 1 :(得分:1)
第一个块在一般情况下是不可能的,因为知道sizeof(A)
(对于类)需要知道sizeof(A)
是什么(对于成员)。
第二种情况的不同之处在于,即使成员函数的定义在语法 inside 类中,语言也会将该定义视为类的外部。编译器将翻译该代码,就像您输入的那样:
class A {
public:
A& operator=(A a);
};
inline A& A::operator=(A a) { return *this; }
声明获取或返回不完整类型的对象的函数是合法的。当真正使用类型时,在类外部的函数定义中,类型已经完成,所以它也非常好。
答案 2 :(得分:0)
看待这种情况的方法是了解如果这实际上是合法的会发生什么。实例化类时,首先构造其所有类成员。因此,在您的示例中,A a
的构造将在A完全构造之前发生,这是不可能的。
此外,这将导致A的对象的无限递归构造。
答案 3 :(得分:-1)
第二个是编译因为你只使用A的引用而不是A的对象。引用不需要完整的类型。但在第一种情况下,你需要A的对象,因此需要完整的类型,这只能在关闭}
之后发生