1.继承
定义某些类时,下级别的成员除了拥有上一级的共性,还有自己的特性,这时候就需要利用继承的技术,减少重复代码。
继承的基本语法 class 子类 : 继承方式 父类
子类 也称为 派生类
父类 也称为 基类
继承方式一共有三种:公共继承,保护继承,私有继承
2.继承中的对象模型
父类中所有非静态成员属性都会被子类继承下去
父类中私有成员属性,是被编译器隐藏了,因此访问不到,但是确实存在,被继承下去了
利用开发人员命令提示工具查看对象模型
跳转盘符 D:,跳转文件路径 cd 具体路径下,查看命名 dir,cl /d1 reportSingleClassLayout类名 文件名
4.继承中构造和析构顺序:先构造父类,再构造子类;先析构子类,再析构父类
5.继承同名成员的处理方式
访问子类同名成员,直接访问即可;
访问父类同名成员,需要加作用域:如果子类中出现和父类同名的成员函数,子类的同名成员函数会隐藏掉父类中所有的同名成员函数,如果通过子类访问对象,访问父类中同名成员,需要加作用域;
6.继承同名静态成员处理方式
访问子类同名成员,直接访问即可
访问父类同名成员,需要加作用域
7.多继承语法:C++允许一个类继承多个类
语法:class 子类 : 继承方式 父类1 , 继承方式 父类2 ...
class Base1{
public:
int m_A;
Base1()
{
m_A = 100;
}
};
class Base2{
public:
int m_A;
Base2()
{
m_A = 200;
}
};
class Son :public Base1, public Base2{
public:
int m_C;
int m_D;
Son()
{
m_C = 300;
m_D = 400;
}
}; //cout << "size of s = " << sizeof(s) << endl; //16
多继承问题:容易出现二义性,出现同名成员时需加作用域区分
8.菱形继承:两个子类继承同一个父类,又有某个类同时继承两个子类,这种继承被称为菱形继承,或钻石继承
典型的菱形继承案例
动物m_Age
↙ ↘
羊m_Age 骆驼m_Age
↘ ↙
羊驼m_Age、m_Age
两份数据 产生二义性
利用虚继承,可以解决菱形继承的问题(子类继承两份相同的数据,导致资源浪费)
继承之前加上关键字 virtual 变为虚继承
Animal类称为虚基类
class Animal
{
public:
int m_Age;
};
class Sheep :virtual public Animal
{
};
class Camel :virtual public Animal
{
};
class SC :public Sheep,public Camel
{
};
void test1()
{
SC sc;
//sc.m_Age = 18;//error
sc.Sheep::m_Age = 18;
sc.Camel::m_Age = 20;
cout << "sc.Sheep::m_Age = " << sc.Sheep::m_Age << endl;
cout << "sc.Camel::m_Age = " << sc.Camel::m_Age << endl;
sc.m_Age = 21;
cout << "sc.m_Age = " << sc.m_Age << endl;
}
int main()
{
test1();
return 0;
}
vbptr 虚基类指针 virtual base pointer ---> vbtale虚基类表 Sheep vbptr→地址0 偏移量为8 0+8→m_Age Camel vbptr→地址4 偏移量为4 4+4→m_Age 两个vbptr加偏移量指向同一个地址,数据唯一