继承
继承是面向对象三大特性之一 减少重复代码
语法 class 子类:继承方式 父类
子类也称为派生类;父类也称为基类
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
//继承实现
//公共页面类
class BasePage{
public:
void header(){
cout<<"公共头部"<<endl;
}
void footer(){
cout<<"公共底部"<<endl;
}
void left(){
cout<<"公共分类列表"<<endl;
}
};
//Java 页面
class Java: public BasePage{
public:
void content(){
cout<<"Java"<<endl;
}
};
//C++页面
class CPP: public BasePage{
public:
void content(){
cout<<"CPP"<<endl;
}
};
void test01(){
Java java;
CPP cpp;
java.footer();
java.content();
cpp.footer();
cpp.content();
}
int main(){
test01();
}
继承方式:
公共继承;保护继承;私有继承
继承中的对象模型
父类中所有非静态成员属性都会被子类继承下去
父类中私有成员属性被编译器隐藏,无法访问,但确实被继承。
继承中构造和析构顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数
继承中构造和析构顺序如下:先构造父类,再构造子类;先析构子类,再析构父类。
继承同名成员处理方式
当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据?
访问子类同名成员,直接访问即可;
访问父类同名成员,需要加作用域。
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class Base{
public:
Base(){
m_A=100;
}
void func(){
cout<<"Base"<<endl;
}
void func(int a){
cout<<"Base int a"<<endl;
}
int m_A;
};
class Son: public Base{
public:
Son(){
m_A=200;
}
void func(){
cout<<"Son"<<endl;
}
int m_A;
};
void test01(){
Son s;
cout<<s.m_A<<endl;
cout<<s.Base::m_A<<endl;//同名成员属性
}
void test02(){
Son s1;
s1.func();
s1.Base::func();//同名成员函数
//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数,
如果想访问到父类中被隐藏的同名成员函数,需要加作用域
s1.func(100);
s1.Base::func(100);
}
int main(){
test02();
}
继承中同名静态成员处理方式
静态成员和非静态成员出现同名,处理方式一致
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class Base{
public:
static int m_A;
static void func(){
cout<<"Base"<<endl;
}
};
int Base::m_A=100;//静态成员变量,类内声明,类外初始化
class Son: public Base{
public:
static int m_A;
static void func(){
cout<<"Son"<<endl;
}
};
int Son::m_A=200;
void test01(){
//同名静态成员属性
Son s;
//1.通过对象访问
cout<<s.m_A<<endl;
cout<<s.Base::m_A<<endl;
//2.通过类名访问
cout<<Son::m_A<<endl;
//第一个::代表通过类名的方式访问
//第二个::代表父类作用域下
cout<<Son::Base::m_A<<endl;
}
void test02(){
Son s1;
s1.func();
s1.Base::func();
//通过类名
Son::func();
Son::Base::func();
}
int main(){
test01();
test02();
}
多继承语法
语法:class 子类 : 继承方式 父类1 ,继承方式 父类2 。。。
多继承可能会引发父类中有成员出现,需要加作用域区分
菱形继承(钻石继承)
两个子类继承同一个父类
又有某个类同时继承两个子类
菱形继承的问题:
羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性;
草泥马继承自动物的数据继承了两份,其实这份数据只需要一份即可。
vbptr virtual base pointer 虚基类指针 指向 virtual base table
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class Animal{
public:
int m_Age;
};
//利用虚继承 解决菱形继承的问题
//继承前加上关键字 virtual变为虚继承,Aniaml类称为虚基类
class Sheep:virtual public Animal{
};
class Tuo:virtual public Animal{
};
class SheepTuo:public Sheep,public Tuo{
};
void test01(){
SheepTuo st;
//当菱形继承,两个父类拥有相同数据,需要加作用域区分
st.Sheep::m_Age=18;
st.Tuo::m_Age=28;
//这份数据只需要一份,菱形继承导致数据有两份,浪费资源
cout<<st.m_Age<<endl;
}
int main(){
test01();
}