C/C++_的不完整类型详解(参考了各位大佬整理下来,特此鸣谢)

一、不完全类型的定义(它是个啥)

定义:已经声明但是尚未定义的类型。不完全类型不能用于定义变量或者类的成员,但是用不完全类型定义指针或者引用是合法的。(来自C++ Primer P274)

对于类型来说:

声明(引用声明):告诉编译器这个类型已经存在,但此时编译器并不知道需要给该类型的对象分配多少字节的内存。

定义(定义声明):描述了该类型的细节,编译器由此可以知道需要给该类型的对象分配多大的内存。

换句话说,不完全类型的定义 就是 尚未定义完全的类型。(编译器尚不知道给该类型对象分配多大内存)

在C/C++,不完全类型的表现形式有这几种 void未指定长度的数组 以及 具有非指定内容的结构和联合

void比较特殊,因为它是内置的不完全类型,用户无法通过定义完整,使得编译器知道该类型对象该分配多大内存。并且void应用的场合也仅是特殊函数的返回值和参数。(eg :malloc() )

class a;
union b;
int c[];

在此时,以上类型 a, b,c 都是不完全类型。

扫描二维码关注公众号,回复: 3487386 查看本文章

如果 紧接着 定义该类型的对象使用该类型都是错误的

class a;
union b;
int c[];

a test_class;//错误,编译器不知到给test_class分配多大内存
b test_union;//错误,编译器不知到给test_union分配多大内存
auto test_int = sizeof(c);//错误,编译器尚未给test_int分配内存,报错不允许使用不完整的类型

切记,在使用该类型或定义该类型的对象,一定确保该类型已经被定义过了。

但 不完全类型 允许 如下操作

  • 指向不完全类型的指针 (指针所占内存大小确定,32机器 4个字节, 64位机器8个字节,因此编译器可直接创建)
  • 不完全类型的引用        ( 引用类型不占储存单元,因此可以创建)
  • 不完全类型的 typedef 名称
  • 返回不完全类型的函数        (eg:void test()  {return f();}   说明: f() 在 test() 之前只有声明没有定义)
  • 不完全函数参数类型            (eg: void test( int , int&)      说明:声明test()时没有指定形参名字)

上面比较特殊的是函数,用这样一句话解惑

函数在被声明之后,定义之前。被调用是合法且有效的。

二、不完全类型出现的场景

1.普通场景,在全局中声明了该类型而未进行定义时,进行定义该类型的对象和使用该类型(eg:参见定义讲解)

2.在两个结构相互包含对方类型的对象

class b;

class a
{
public:b test_b;
};

class b
{
public:a test_a;

};

class a 中的定义 便会报错 不允许使用不完整的类型

相对的class b中的定义不会出错,因为 在执行 a test_a;前 class a已经定义完整。

3.某class的友元使用了该class定义对象,但是该class的友元定义在该class之前。

class a;
void test()
{
	a x;
}

class a
{
	friend void test();

private:
	int b= 2;
};

三、不完全类型带来的好处(什么时候该用不完全类型)

1.提高代码的灵活性

char str[];
char str[10];

当编译器碰到第一个声明时,认为str是一个不完全类型,碰到第二个声明时str就组合成完全类型了.

eg:当我们需要一块内存,但并不知道要申请多大时。在 .h文件里声明一个数组 char b [];在.c文件我们再声明完全,就可以很方便的改变数组长度。并且编译的时候也不用再编译一次头文件。

2.不完全类型允许使用指针、引用类型。在期间保证了类型的封装型。

四、不完全类型使用时需要注意的地方

 

千万千万,一定一定记住

在使用该类型或定义该类型的对象,一定确保该类型已经被定义过了。

猜你喜欢

转载自blog.csdn.net/lovely_ke/article/details/82949556