C++联合枚举和类型别名
联合 union
联合是一种特殊的类一个union联合可有多个数据成员 这些数据成员共同使用同一片存储空间(这样的机制目的是节省内存)
1.分配给一个union对象的存储空间至少要能容纳它的最大数据成员
2.union中不能含有引用类型的成员,默认情况下,union的成员都是公有的,这一点和struct相同
3.union既不能继承自其他类,也不能作为基类使用,所以在union中不能含有虚函数
4.为union的一个数据成员赋值时会令其它数据成员变成未定义的状态
联合
//可以像创建结构一样创建联合
union keywords
{
unsigned long Birthday;
unsigned short ssn;
const char *pet;
};
结构体内变量Birthday
,ssn
,*pet
是共用一块内存的,即&Birthday=&ssn=&pet
,且此union联合体所占的内存的长度由联合体中占空间最大的成员决定
所以在keywords
这个联合体中,其内存由Birthday
决定,所以他们实际存储的值只有一个,即最后赋值的那个,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间,当访问其内成员时可用.
和->
来直接访问
注意:
const char *pet
: 声明了一个指向字符或常量字符串的指针(其中pet
所指向的内容不可修改 因为要输入字符串 而char
为单字符类型 需要用pet
的这个字符串的第一个参数的地址 进行字符串的查找)
联合
keywords key;
key.Birthday = 20000912;// key.Birthday第一次赋值
cout << key.Birthday << endl;//读取正常
key.pet = "wangcai";//key.pet第一次赋值
cout << key.pet << endl;//读取正常
cout << key.Birthday << endl;//再次读取时key.Birthday第一次赋值为无效
结果
可以看出,由于联合体中的几个成员都使用一个内存所以他们实际存储的值只会是结构体最后赋值的成员的值
枚举 enum
枚举类型(enumeration)是C++中的一种派生数据类型,枚举是用户定义的若干枚举常量的集合
定义格式:枚举类型的定义格式为
enum <类型名> {<枚举常量表>};
关键字enum : 指明其后的标识符是一个枚举类型的名字
枚举常量表 : 由枚举常量构成, “枚举常量” 或称 “枚举成员” ,是以标识符(变量名)
形式表示的int整型量
,表示枚举类型的取值.枚举常量表用于列出枚举类型的所有取值,各枚举常量之间以,
间隔符间隔,且各枚举常量必须各不相同,取值类型与条件表达式相同
例如:
enum weekdays { zero, one, two, three, four };
编译器会按照各个枚举值在定义时出现的先后顺序把他们与0~n~1
的整数 分别关联起来(其中n
是枚举值的总个数,也就是说枚举值其实是枚举类型中的序号)
枚举的值不需要使用双引号(枚举成员不是字符串,是以标识符形式表示的整型量
注 :枚举常量只能以标识符形式表示,而不能是整型、字符型等文字常量(标识符的意义相当于变量的变量名)
定义一个枚举类型后 像这样创建该类型的变量
weekdays today;// 声明枚举类型weekdays 变量today
today = one;
cout << "今天星期" << today << endl;//输出值为 1 因为one在枚举类型weekdays中序号为1
today = two;
cout <<"明天星期"<< today << endl;//输出值为 2 因为two在枚举类型weekdays中序号为2
运行结果:
注意:🎯
枚举值另外的一个作用是可以作为switch
语句的条件case标号
类型别名typedef
typedef是C/C++语言中保留的关键字,用来定义任意一种数据类型的别名,需要注意的是typedef并没有创建新的类型,只是指定了一个类型的别名而已 typedef定义的类型的作用域只在该语句的作用域之内,也就是说如果typedef定义在一个函数体内,那么它的作用域只存在于这个函数体内
typedef符经常使用的场景:
1.指定一个简单的别名,避免了书写过长的类型名称(类似于宏定义)
2.实现一种定长的类型,在跨平台编程的时候尤其重要
3.使用一种方便阅读的单词来作为别名,方便阅读代码
typedef int* IP;//给int类型定义一个别名 名为intpointer
🔥此行代码定义了IP是一个int类型的指针,也就是说IP的类型是int*(也可以直接定义类型名)
此后每当定义整型指针时,就可以使用IP
这个类型名来进行指代定义,例如:
int a = 5;
IP i = &a; //此时intpointer为int整型指针类型
cout << *i;
结果
完整代码
#include <iostream>
using namespace std;
//todo 联合
//可以像创建结构一样创建联合
union keywords
{
unsigned long Birthday;
unsigned short ssn;
const char *pet;
//声明一个指向字符或字符串常量的指针(p所指向的内容不可修改 因为要输入字符串 而char为单字符类型 需要用pet的这个字符串的第一个参数的地址 进行字符串的查找)
//变量Birthday ssn *pet 是共用一块内存的 即 &Birthday = &ssn= & pet 内存的长度由联合体中占空间最大的成员决定
//在keywords这个联合体 内存长度由Birthday决定 所以他们实际存储的值只有一个,即最后赋值的那个
//利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问
};
//todo枚举
//编译器会按照各个枚举值在定义是出现的先后顺序把他们与0~n-1的整数 分别关联起来(n是枚举值的总个数 也就是说枚举值其实是枚举类型中序号)
enum weekdays { zero, one, two, three, four };
//枚举的值不需要使用双引号(枚举成员不是字符串,是以标识符形式表示的整型量 表示枚举类型的取值。枚举常量表列出枚举类型的所有取值,各枚举常量之间以","间隔,且必须各不相同。取值类型与条件表达式相同)
//todo注 :枚举常量只能以标识符形式表示,而不能是整型、字符型等文字常量
int main()
{
//todo联合
keywords key;
key.Birthday = 20000912;
cout << key.Birthday << endl;
key.pet = "wangcai";
cout << key.pet << endl;
//由于联合体中的几个成员都使用一个内存所以他们实际存储的值只有一个,即最后赋值的那个
cout << key.Birthday << endl;
//cout << key.Birthday << endl;//key.pet的第一个元素的首地址
//todo枚举
//定义一个枚举类型后 像这样创建该类型的变量
weekdays today;// 声明枚举类型weekdays 变量today
today = one;
cout << "今天星期" << today << endl;//输出值为 1 因为one在枚举类型weekdays中序号为1
today = two;
cout <<"明天星期"<< today << endl;//输出值为 2 因为two在枚举类型weekdays中序号为2
//todo枚举值可以作为switch语句的条件case标号
//todo类型别名
typedef int* intpointer;//给int类型定义一个别名 名为intpointer
//此后每当定义整型指针时 就可以使用intpointer这个类型名来进行定义
//这行代码定义了 intpointer是一个int类型的指针,也就是说intpointer的类型是int*(也可以直接定义类型名)
int a = 5;
intpointer i = &a; //此时intpointer为int整型指针类型
cout << *i;
return 0;
}
运行效果