多继承-虚函数
如果子类继承的多个父类都有虚函数, 那么子类对象就会产生对应的多张虚表.
同名函数
同名成员变量
多继承2-菱形继承
菱形继承带来的问题:
最底下子类从基类继承的成员变量冗余, 重复(有两个age, 内存是两份, 从语法上正确, 但不合理)
最底下子类无法访问基类的成员, 有二义性.
多继承3-虚继承
虚继承可以解决菱形继承带来的问题
Student和Worker共用一个age, 共享
从虚基类里面搞过来的成员变量都放到最后面, 这个对象会多出4个字节, 存放虚表指针, 20和12是拿来寻找age的, 拿来定位虚基类的成员变量在哪里, 因为age是共享的, 所以就要保证不管是从Worker这个类开始找还是从Student这个类开始找, 都能找到age.
Person类被称为虚基类
静态成员(static)
◼ 静态成员:被static修饰的成员变量\函数
□可以通过对象(对象.静态成员)、对象指针(对象指针->静态成员)、类访问(类名::静态成员)
◼ 静态成员变量
□ 存储在数据段(全局区,类似于全局变量),整个程序运行过程中只有一份内存, 不在类里面
□ 对比全局变量,它可以设定访问权限(public、protected、private),达到局部共享的目的
□ 必须初始化,必须在类外面初始化,初始化时不能带static,如果类的声明和实现分离(在实现.cpp中初始化)
◼ 静态成员函数
□ 内部不能使用this指针(this指针只能用在非静态成员函数内部)
□ 不能是虚函数(虚函数只能是非静态成员函数)
□ 内部不能访问非静态成员变量\函数,只能访问静态成员变量\函数
□ 非静态成员函数内部可以访问静态成员变量\函数
□ 构造函数、析构函数不能是静态
□ 当声明和实现分离时,实现部分不能带static
静态成员经典应用-单例模式
单例模式:设计模式的一种, 保证某个类永远只创建一个对象.
1.构造函数\析构函数私有化, 拷贝构造函数私有化, 赋值运算符重载函数私有化.
2.定义一个私有的static成员变量指向唯一的那个单例对象
3.提供一个公共的访问单例对象的接口.
#include <iostream>
using namespace std;
class Rocket {
private:
Rocket() {}
static Rocket *ms_rocket;
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;
// 防止野指针
}
}
void run() {
cout << "run()" << endl;
}
};
Rocket *Rocket::ms_rocket = NULL;
int main()
{
Rocket *p = Rocket::sharedRocket();
p->run();
p->deleteRocket();
return 0;
}
(1)为什么要用指针?
1.在C++开发中, 对象能放堆空间, 尽量放堆空间.
2.对于单例对象, 要考虑内存的灵活使用, 因为牵扯到内存的分配和销毁, 所以用堆空间更灵活.
(2)赋值运算符重载函数为什么要私有化?
因为两个一样的对象做赋值操作没有意义.
(3)拷贝构造函数为什么要私有化?
因为如果不写拷贝构造函数, 还可以通过调用默认的拷贝构造函数去构建对象.如:
Rocket *p1 = Rocket::sharedRocket();
Rocket *p2 = new Rocket(*p1)