继承
动物有猫、狗, 猫又分为加菲猫、布偶猫......;狗又有哈士奇、德国牧羊犬......
我们发现,下一类除了拥有上一类的共性之外,还拥有自己的特性。
于是我们可以利用继承的方式来减少重复的代码
继承的基本语法
class A:public B
A称为子类 或 派生类
B称为父类 或 基类
子类中的成员主要分为两大类
一类是从父类中继承过来的,我们叫做共性
一类是子类自己定义的,我们叫特性
继承的好处:减少重复的代码
//继承的基本语法
class BasePage {
public:
void header() {
cout << "首页、公开课、登录、注册...(公共头部)" << endl;
}
void footer() {
cout << "帮助中心、联系方式、站内地图...(公共底部)" << endl;
}
void left() {
cout << "Java、Python、C++...(公共列表)" << endl;
}
};
class Java :public BasePage
{
public:
void content() {
cout << "Java学科视频" << endl;
}
};
class Python :public BasePage
{
public:
void content() {
cout << "Python学科视频" << endl;
}
};
class CPP :public BasePage
{
public:
void content() {
cout << "CPP学科视频" << endl;
}
};
void test01() {
Java ja;
ja.header();
ja.footer();
ja.left();
ja.content();
cout << "------------" << endl;
Python py;
py.header();
py.footer();
py.left();
py.content();
cout << "------------" << endl;
CPP cpp;
cpp.header();
cpp.footer();
cpp.left();
cpp.content();
cout << "------------" << endl;
}
int main()
{
test01();
}
继承方式
继承语法:class 子类:继承方式 父类
继承方式分为三种:公共继承、保护继承、私有继承
公共继承:公共成员、保护成员位置不变,私有成员不可访问
保护继承:公共成员、保护成员位于保护位置,私有成员不可访问
私有继承:公共成员、保护成员、私有成员都不可访问
注意:虽然不可访问,但是子类中确实继承了这些成员,只是被隐藏了,子类的子类也会继承这些属性。
继承中的对象模型
先敲一段代码
//继承中的对象模型
class Base {
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class Son :public Base {
public:
int m_d;
};
int main()
{
Son s1;
cout << "size of Son=" << sizeof(s1);
}
利用sizeof计算类的长度,可以验证上一点讲的私有成员或私有继承不可访问但确实存在于子类中
下面再利用开发人员命令提示符用模型观察
继承中构造和析构顺序
利用上面的模型也可以说明继承中 父类先构造、子类后构造(先有父亲再有儿子)
然后依据先进后出的原理,子类先析构、父类后析构
继承同名成员处理方式
//继承同名成员(非静态)的调用方式
class Base {
public:
int m_a = 10;
void fun() {
cout << "父类的func" << endl;
}
void fun(int a) {
cout << "父类的func 含参" << endl;
}
};
class Son :public Base {
public:
int m_a = 100;
void fun() {
cout << "子类的func" << endl;
}
};
void test01() {
Son s1;
cout << s1.m_a << endl;//子类对象直接调用的是子类成员
cout << s1.Base::m_a << endl;//子类对象加上父类作用域运算符调用的是父类成员
s1.fun();
s1.Base::fun();
//s1.fun(100);报错,因为子类、父类函数同名情况下,子类会隐藏父类的所有同名成员函数,
//要访问则加上作用域运算符
s1.Base::fun(1000);
}
int main()
{
test01();
}
总结:1、子类对象直接访问的是子类同名成员
2、子类对象加上作用域可以访问父类同名成员
3、子类和父类成员函数同名情况下,子类会隐藏父类中同名函数,子类对象加上作用域运算符可以访问父类同名函数
继承同名静态成员处理方式
//继承中同名的静态成员
class Base {
public:
void func() {
cout << "diao1" << endl;
}
static int a;
};
int Base::a = 8;//要加上作用域
class Son :public Base {
public:
void func() {
cout << "diao2" << endl;
}
static int a;
};
int Son::a = 9;
int main()
{
Son s1;
s1.func();
s1.Base::func();
cout << s1.a << endl;
cout << s1.Base::a << endl;
cout << Son::a << endl;
cout << Son::Base::a << endl;
//总结:对于类的非静态成员 通过对象访问
//对于静态成员 1.通过对象访问
// 2.通过类名访问
}
多继承语法
class Base1 {
public:
Base1(){
m_A = 10;
}
int m_A;
};
class Base2 {
public:
Base2() {
m_A = 100;
}
int m_A;
};
class Son :public Base1, public Base2 //实际开发不建议使用多继承,多个程序员设置相同成员,影响使用
{
};
void test01() {
Son s1;
//s1.m_A;父类成员同名,加作用域以区分
cout << "Base1中m_A=" << s1.Base1::m_A << endl;
cout << "Base2中m_A=" << s1.Base2::m_A << endl;
}
int main()
{
test01();
}
菱形继承
//菱形继承
class Animal { public:int m_Age; };
class Sheep :virtual public Animal {};//继承前加virtual关键字,变为虚继承,继承的父类被称为虚基类
class Tuo:virtual public Animal {};//实际上是改为传递两个指针,指针都指向m_Age
class SheepTuo: public Sheep, public Tuo{};
void test01() {
SheepTuo yt;
yt.Sheep::m_Age = 19;
yt.Tuo::m_Age = 29;
yt.m_Age = 39;//若没有virtual,则此操作报错
cout << "yt.Sheep::m_Age =" << yt.Sheep::m_Age << endl;
cout << "yt.Tuo::m_Age =" << yt.Tuo::m_Age << endl;
cout << "yt.m_Age =" << yt.m_Age << endl;
}
int main()
{
test01();
}
菱形继承为子类继承父类中两份相同的数据,造成资源浪费和无意义
利用虚继承可以解决,虚继承后变为同一份数据