今天我这里下雪了 很冷 你哪里呢?
我们 来谈谈 自定义类型
这只是一个称呼
包含有 结构体(struct) 类(class) 共用体(union)
枚举(enum)
我们编程基本要常常与自定义类型 打交道
进行面向对象编程方式
自定义类型 有个比较重要的概念:
访问权限修饰符
private (私有)
protected (血亲私有)
public (公开)
private 私有 很好理解
只能在自己的内部访问到
protected (血亲私有)
应该叫继承链私有 只有子父类的内部有权限访问
public (公开)
公开不必说 在任何地方通过实例化的对象都可访问
说说 struct 结构体
语法规则
struct name { } (可选)实例化对象名称;
它大括号内部可以装填 变量与函数
如
struct a
{
//默认访问权限修饰符为 public
int b;
int function(a* n){ return 0;};
}
int main()
{
struct a A; //创建 struct a 类型的 A变量(对象)
a A1; //创建 struct a 类型的 A1变量(对象)
A1.b = 100;//给A1变量中的成员变量 b 赋值 100
std::cout ‹‹ A1.b;//100
A1.function(nullptr);//这是A1中的成员函数调用
a * pA1 = &A1;//& 取地址符 没忘吧? 初始化 a类型的指针变量
pA1 -›b;//100 通过指针变量pA1去访问成员b
*pA1.b;//这个也是指针访问成员b 不过与-›有区别
return 0;
}
上述 有几个 关键
一:
. 注意这个小点( 对象成员访问符 ) 你想访问自定义类型 变量中的 成员 就得使用它
二:
-› 这是一个箭头 你想通过自定义类型的指针 变量 去访问 该地址的使用此类型解释时的对应成员 就得用它
三:
* 解引用 (我喜欢叫 解地址符 因为本质它就是拿到这个地址所代表的类型对应的变量)
就如上述
*pA1 与 *pA1.b 意义是不同的 二者都有解释
*pA1 是 通过pA1中存储的地址 去 拿到该指针类型 对应的变量
就是 我指针是 自定义类型的 拿到的这个变量就是自定义类型的
是 基本数据类型的 拿到的变量就是 基本数据类型的
恩…我画个图个你们瞅瞅 理解理解
先设定一下
比如
struct B
{
int c;//四字节
int b;//四字节
}
sizeof( B ) = 8 字节 没问题吧
sizeof 关键字 可以计算类型 或 变量所需的大小
它编译期就可确定的 无法动态
现在我们要写下这个
B object(100,200); //object.b = 100 object.c = 200 这是struct初始化的一种方法
B* pOBJ = &object;//初始化指针变量 将 object 的地址 存进 pOBJ中
int * pInt = (int*)pOBJ;//强制类型转换为int* 且将 pOBJ 中存储的值 初始化给 pInt
简单来说 pOBJ 中存的数值 与 pInt 中 是一致的
假如 pOBJ 中存储的值是
0x00000100 四字节的指针(32位下)
则 object 的内存分布如下
用 *pOBJ 去访问
拿到的内存块是
*pInt 拿到的内存块
我的理解是 首先
指针变量 里存的只是数值而已
而指针类型让计算机知道这数值代表的是地址
且使用用该地址时 应该的解释类型
就像上述 pOBJ 类型是 B*
按照B类型去解释 0x00000100
我们就去找到这个内存位置 然后向后数 8个内存块 (B类型大小为 8 字节 ) 具体内部依然细分 直到 分为 简单的基本数据类型为止
所以 *pInt 才会出现 在同一内存位置 只拿了前4个内存块 因为指针解释类型是 int 的
而所谓的指针运算 其实也是差不多的概念
如
执行了 pInt++;
pInt 应该为几? 之前是 0x00000100
答案是 应该为 0x00000104
如果是 pOBJ+1 是多少呢?
大家应该知道怎么推理了
首先 看 pOBJ 中值 是多少 是 0x00000100
其次 看是什么类型的指针 B* 类型
解释类型是 B sizeof B = 8
所以 运算结果是
0x00000100 + 8 = 0x00000108
想那些数组指针 也是如此运算的
如
char b[ 10 ] = { 0 };// 假定 &b = 0x00000000
char (*pb)[10] = &b;
pb + 1 = ?
答案是 0x00000000+10=0x00000010
首先 先看pb内存的值是多少 0x00000000
其次看pb的指针类型 char (*)[10]
解释类型 char[10]
数组元素 是char 有 10个
计算 0x00000000 + ( 1 * 10) = 0x00000010
sizeof char = 1
0x00000000 + ( sizeof char * 10) = 0x00000010
思索一下二维数组
char b2[ 10 ][5] = { 0 };// 假定 &b = 0x00000000
char (*pb2)[10][5] = &b2;
pb2 + 1 = ?
0x00000000 + ( sizeof char * (10 * 5 ) ) = 0x00000050
我应该没弄错 你可以在编译器里 运行看看 输出的地址值 偏移是否是 50
所以类型很重要 在指针上面来说我们可以随意更改 指针变量中 地址 的解释类型
给你们说个例子
struct B
{
int c;//四字节
int b;//四字节
}
struct B2
{
short a;//二字节
short b;//二字节
int c;//四字节
}
// main 函数中
B object(100,200); //object.c = 100 object.b= 200 这是struct初始化的一种方法
B* pOBJ = &object;//初始化指针变量 将 object 的地址 存进 pOBJ中
int * pInt = (int*)pOBJ;//强制类型转换为int* 且将 pOBJ 中存储的值 初始化给 pInt
B2* pb2 = (B2*)&objec;
pb2 -›a = 1;
pb2 -›b = 1;
object.c 为多少
答案是 257
分析一下内存分布
B类型是这样的
而B2类型是这样的
我们看看最开始
object.c = 100 时
内存里面的数值(十六进制显示)
而 当地址被强转为 B2*时 且被修改
B2* pb2 = (B2*)&object;
pb2 -›a = 1;
pb2 -›b = 1;
*pb2 同一块地址的 内存分布中数值是
而此时 object.c = 0x0101 (257)
未完待续…很晚了 明见