Bootstrap

C++不完整类型incomplete type 浅析

C++不完整类型incomplete type 浅析

类型定义:
The following are incomplete types:
• Type void
• Array of unknown size
• Arrays of elements that are of incomplete type
• Structure, union, or enumerations that have no definition
• Pointers to class types that are declared but not defined
• Classes that are declared but not defined

代码示例:

•	template<class T> inline void checked_delete(T* x)  
•	{  
•	  typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];  
•	  (void) sizeof(type_must_be_complete);  
•	  delete x;  
•	}  
•	  
•	template<class T> inline void checked_array_delete(T* x)  
•	{  
•	  typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];  
•	  (void) sizeof(type_must_be_complete);  
•	  delete[] x;  
•	}

    分析:这两个函数是函数模版,在编译时无法确定参数的类型,而动态运行时的错误是比较棘手的,所以用这行来将运行时错误转变为编译期错误。这句话其实就是定义了一个固定大小的char型数组,数组名为type_must_be_complete,数组大小是多少呢?sizeof(T)?1:-1, ?:这个三元操作符大家都很熟悉了,若sizeof(T)非0,这个表达式的值为1,即typedef了一个大小为1的char型数组,否则定义一个大小为-1的数组。数组大小还能为负数?当然不能,于是就会报错,而且是编译期错误,于是就将一个动态运行时错误在编译时就发现了。前向声明就是:可以声明一个类而不定义它。

     class Screen;//declaration of the Screen class

    这个声明,有时候被称为前向声明(forward declaration),在程序中引入了类类型的Screen。在声明之后,定义之前,类Screen是一个不完全类型(incompete type),即已知Screen是一个类型,但不知道包含哪些成员.不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数.为什么:这是因为不知道这个类型的占用的空间大小(void)强制类型转换,消除编译器对未使用sizeof返回值的警告。GCC对于incomplete type使用sizeof时,会返回0。总结incomplete type就是那些声明了,但没有定义的类型。
    C++声明了一个函数可以不进行定义,只要这个函数只用在不求值的场合(unevaluated context),也就是没有可能被执行,也没有被取地址。C++11标准库就包含一个没有定义的函数(确切的说是函数模板)。
template< class T >typename std::add_rvalue_reference<T>::type declval();

;