继承的语法
class 子类 : 继承方式 父类
继承的三种方式
公共继承
保护继承
私有继承
首先,对于父类A,有三种权限的内容,公共权限内容a,保护权限内容b,私有权限内容c。
其次,对于子类B,也有三种方式继承父类A的内容,公共继承、保护继承、私有继承。
无论是哪种继承方式,子类B只能继承父类的公共权限内容和保护权限内容,但是不能访问私有权限内容。也就是说,对于父类A中的公共权限内容a和保护权限内容b,子类B可以继承。但是父类A中的私有权限内容c,子类B是无法访问的。
公共继承
在公共继承中,父类A的公共权限和保护权限在子类B中保持不变。也就是说,父类A中,a是公有权限,b是保护权限,在子类B中,a也是公有权限,b也是保护权限。子类无法访问父类的私有权限c。
保护继承
在保护继承中,父类A的公共权限和保护权限在子类B中都变成了保护权限。也就是说,父类A中,a是公有权限,b是保护权限,在子类B中,a和b都变成了保护权限内容。子类无法访问父类的私有权限c。
私有继承
在私有继承中,父类A的公共权限和保护权限在子类B中都变成了私有权限。也就是说,父类A中,a是公有权限,b是保护权限,在子类B中,a和b都变成了私有权限内容。子类无法访问父类的私有权限c。
三种方式的实现
父类
class Base1
{
public:
int mA;
protected:
int mB;
private:
int mC;
};
子类1——公共权限继承
class Son1 :public Base1
{
public:
void func1()
{
mA = 55;//父类中公共权限成员 子类中仍然是公共权限
mB = 45;//父类中保护权限成员 子类中仍然是公共权限
//mC = 45;//父类中私有权限成员 子类无法访问
}
};
void test1()
{
Son1 son1;
son1.mA = 100;//在Son1中是公共权限类内可以访问,类外都可以访问
//son1.mB = 100;//在Son1中是保护权限,类内可以访问,类外无法访问
}
子类2——保护权限继承
class Son2 :protected Base1
{
public:
void func()
{
mA = 55;//父类中公共权限成员 子类中变为保护权限
mB = 45;//父类中保护权限成员 子类中变为保护权限
//mC = 45;//父类中私有权限成员 子类无法访问
}
};
void test2()
{
Son2 s;
//s.mA = 100;//在Son2中,mA是保护权限,类外不可以访问
//s.mB = 100;//在Son2中,mB是保护权限,类外不可以访问
}
子类3——私有权限继承
class Son3 :private Base
{
private:
void func()
{
mA = 55;//父类中公共权限成员 子类中变为私有权限
mB = 45;//父类中保护权限成员 子类中变为私有权限
//mC = 45;//父类中私有权限成员 子类无法访问
}
};
class GrandSon3 :public Son3
{
public:
void func()
{
//对于GrandSon3而言,其父类是Son3,Son3中mA和mB都是私有权限,类内也无法访问
//mA = 90;
//mB = 90;
}
};
void test3()
{
Son3 s;
//s.mA = 100;//在Son3中,mA是私有权限,类外不可以访问
//s.mB = 100;//在Son3中,mB是私有权限,类外不可以访问
}
继承的三种方式的总结:重点在于这张图
无论是哪种继承方式,子类B只能继承父类A的公共权限内容和保护权限内容,不能访问私有权限内容。其中:
公共权限类内、类外都可以访问;
保护权限类内可以访问,类外不可以访问;
私有权限类内、类外都不可以访问。
继承中的对象模型
问题
子类可以继承父类所有共性的内容,也就是可以继承公共权限的内容。那么,从父类继承过来的成员,哪些属于子类对象中?这些公共权限的内容是否属于子类呢?
场景描述
父类中有公共权限、保护权限、私有权限的内容,子类中使用公共继承的方式继承了父类,并且具有自己特性。通过查看子类的内存大小来判断,父类中的内容属不属于子类。
#include <iostream>
using namespace std;
class Base
{
public:
int mA;
protected:
int mB;
private:
int mC;//私有成员只是被隐藏了,但是还是会继承下去
};
class Son :public Base
{
public:
int mD;
};
void test01()
{
cout << "sizeof Son = " << sizeof(Son) << endl;
}
int main() {
test01();
system("pause");
return 0;
}
由此说明,父类中所有非静态成员属性,不管是公共、保护还是私有,都会被子类继承。此外,父类中的私有属性只是被编译器隐藏了,子类无法访问,但可以继承。
查看类对象模型
使用VS自带工具-开发人员命令提示工具,再跳转到当前源文件所在路径,再输入”dir“命令。
可以看到”继承中的对象模型.cpp“这个源文件,再查看这个对象模型
再输入命令”cl /d1 reportSingleClassLayoutSon 31“,
”reportSingleClassLayout“即报告单各类布局;
”Son“是想要查看的类名,也可以换成父类;
由于我的这个文件是第31个,再Son后敲入空格,再输入31,再按一下tab键,就会自动把这个源文件的名字补全。
最后enter,就能看到第31个源文件”...继承中的对象模型“中Son这个类的分布
这个图可以看到:
Son这个对象模型,内存空间是16个字节大小;
父类名称是Base,继承父类的属性是mA、mB、mC;
Son的自身属性是mD。
总结:
子类中继承父类所有非静态成员属性,包括公共、保护、私有成员属性;
私有成员属性也继承了,只是被编译器隐藏,无法访问;
查看类对象模型的方法,利用VS自带工具-开发人员命令提示工具,定位到当前CPP文件的盘符
然后输入: cl /d1 reportSingleClassLayout查看的类名 所属文件名。
继承中构造和析构顺序
问题:
子类继承父类后,当创建子类对象,也会调用父类的构造函数。那么,父类和子类的构造和析构顺序是谁先谁后?
整体实现
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base的构造函数" << endl;
}
~Base()
{
cout << "Base的析构函数" << endl;
}
};
class Son :public Base
{
public:
Son()
{
cout << "Son的构造函数" << endl;
}
~Son()
{
cout << "Son的析构函数" << endl;
}
};
void test1()
{
//Base b;//对象创建在栈上,调用父类Base的构造和析构
Son s;
}
int main() {
test1();
system("pause");
return 0;
}
上图可以说明:
创建子类Son对象s时,也会创建父类Base对象;
先有父类构造函数,再有子类构造函数,因为子类继承了父类,所有得先有父类,才有子类,子类才能继承;
先是子类析构函数,再是父类析构函数。
总结:
继承中,先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反。