菱形继承
- 最底下子类从基类继承的成员变量冗余,重复
- 最底下子类无法访问基类的成员,有二义性
虚继承
- 虚继承可以解决菱形继承带来的问题
- 两个虚继承共用一个m_age
- Person类被称为虚基类
struct Person { int m_age;};
struct Student : virtual Person { ...};
struct Worker : virtual Person { ...};
struct Undergraduate : Student, Worker { ...};
- 虚表指针与本类起始的偏移量(一般是0)
- 虚基类第一个成员变量与本类起始的偏移量
注意上面两句话,这不是学习的环境,因为你只能看见以上两句话,看不懂可以直接放弃理解。学习环境为视频加比喻加图片,生动形象。
- 真实的学习环境理解方式为:仓库拿东西时,你一进门有人告诉你,前面第8个房间(偏移量8)
- 啥时候不能放弃?发现新东西时。在知识面逐渐充足时,明明万事俱备只欠东风时,就需要坚持下去。
静态成员(static)
- 静态成员:被static修饰的成员变量函数
- 存储在数据段(全局区,类似于全局变量),整个程序运行过程中只有一份内存
- 对比全局变量,可以设定访问权限(public、protected、private),达到局部共享的目的
- 必须在类外面初始化,不能使用static
- 内部不能使用this指针,没有对象传地址给this()
class Car {
public:
static int m_price;
void run() {
cout << "run()" << endl;
}
};
// 初始化成员变量
int Car::m_price = 0;
int main() {
Car car1;
car1.m_price = 100;
Car car2;
car2.m_price = 200;
Car::m_price = 300;
Car *p = new Car();
p->m_price = 400;
delete p; //对象销毁与数据段中的静态变量没有关系
getchar();
return 0;
}
静态成员与全局变量是同一个东西,汇编层
class Car{
public:
int m_age;
};
...
Car car1;
car1.m_age = 1;
...
dword ptr [ebp-8],1 //ebp-8,栈空间
class Car{
public:
static int m_price
};
// 在类外面初始化成员变量
int Car::m_price = 2;
dword ptr ds:[00A9A314h],2 //ds,data segment 数据段(全局区)
int g_age; int main() { g_age = 0;}
dword ptr ds:[00A9A318h],0 //与静态成员变量一样
class Car {};
Car g_car; //全局区创建对象
int main() {
Car car; //栈空间创建对象
Car *p = new Car(); //堆空间创建对象
};
单例模式
- 设计模式的一种,保证某个类永远只创建一个对象
1.构造函数私有化
2.定义一个私有的static成员变量指向唯一的那个单例对象
3.提供一个公共的访问单例对象的接口
class Rocket {
private:
Rocket() {} //构造函数私有化
static Rocket *ms_rocket; //定义一个私有的static成员变量指向唯一的那个单例对象
public:
static Rocket *sharedRocket() { //提供一个公共的访问单例对象的接口
if (ms_rocket == NUll) {
ms_rocket == new Rocket();
}
return ms_rocket;
}
static void deleteRocket() {
if (ms_rocket != NULL) {
delete ms_rocket; //只是回收指针的指向
ms_rocket = NULL;
}
}
};
Rocket *Rocket::ms_rocket = NULL;
int main() {
Rocket *p = Rocket::sharedRocket();
}
new、delete的误区
int *p = new int;
*p = 10;
delete p; // 回收堆空间(4个字节),这块空间可以被重新使用