目录
在多种接口需要相同输出时,C++的继承相对于传统方式更有利也更方便维护
C++继承语法:
class 子类:继承方式 父类;
传统方式:
class Java{
public:
void header(){
cout << "首页、公开课" << endl;
}
void footer(){
cout << "帮助中心" << endl
}
}
class Python{
void header(){
cout << "首页、公开课" << endl;
}
void footer(){
cout << "帮助中心" << endl
}
}
void test01(){
cout << "Java下载视频页面如下" << endl;
Java ja;
ja.header();
ja.footer();
cout << "Python下载视频页面如下" << endl;
Python py;
py.header();
py.footer();
}
int main(){
test01();
}
而使用C++继承会显得更加简洁,会让阅读代码的人更加轻松!
C++继承方式:
class BasePage{
public:
void hearer(){
cout << "首页、公开课、登陆 "<<end;
}
void footer(){
cout << "帮助中心、交流合作" << endl;
}
void left(){
cout << "Java、Python " << endl;
}
}
class Java : public BasePage{
public:
void content(){
cout << "JAVA学科视频 " <<endl;
}
}
class Python : public BasePage{
public:
void content(){
cout << "Python学科视 频 " << endl;
}
}
void test01(){
cout << "JAVA下载视频页面如下:" << endl;
Java ja;
ja.heater();
ja.footer();
Python py;
py.heateer();
py.footer();
}
int main(){
test01();
return 0;
}
继承方式
C++的继承方式有三种:
public(公开)、protected(保护)、private(私密)
//继承方式
//公共继承
class Base1{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son : public Base1{
public:
void func(){
m_A = 10; //父类中的公共权限成员 到子类中依然是公共权限
m_B = 10; //父类中的包含权限成员 到子类中依然是保护权限
m_C = 10; //子类中的私有权限成员 子类访问不到
}
};
void test01(){
Son s1;
s1.m_A = 100;
s1.m_B = 100; //到了son中 m_B是保护权限 类外访问不到
}
//保护继承
class Base2{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son2 : protected Base2{
public:
void func(){
m_A = 100; //父类中公共成员 到子类中变为保护权限
m_B = 100; //父类中保护成员,到子类中变为保护权限
//m_C = 100; //父类中的私有成员 子类访问不到
}
}
void test02(){
Son2 s1;
s1.m_A = 100; //在Son2中m_A变为保护权限,因此类外访问不到
s1.m_B = 100; //在Son2中m_B保护权限 不可以访问
}
//私有继承
class Base3{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son3 : private Base3{
public:
void func(){
m_A = 100; //父类中公共成员 到子类中变为了 私有成员
m_B = 100; //父类中保护成员 到子类中变为了 私有成员
m_C = 100; //父类中私有成员,子类访问不到
}
};
class GrandSon3 : public Son3{ //到了son3中 m_A变为私有,即使是儿子 也访问不到
public:
void func(){
m_A = 1000;
m_B = 1000;
}
}
void test03(){
s1.m_A = 10000; //到son3中 变为私有成员 类外访问不到
s1.m_B = 120000; //到son3中 变为私有成员 类外访问不到
}
总的来说:原本父类中就是private和protected的继承方式,到子类中也无法访问
而子类继承时,如果继承方式为private和protected的都会成为相应的权限类型,而更高的权限则不会变动,如:原本是public方式,但是其中有一个变量是private方式,继承过去的方式是protected,类其中public的会变成protected,但是private的不变。
继承同名成员处理方式(父类与子类中都有相同的成员)
访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
//继承中同名成员处理方式
class Base{
public:
Base(){
m_A = 100;
}
void func(){
cout << "Base-func()调用" << endl;
}
void func(int a){
cout << "Base-func(int a) 调用" << endl;
}
int m_A;
};
class Son : public Base{
public:
Son(){
m_A = 200;
}
void func()
{
cout << "Son-func()调用" << endl;
}
int m_A;
}
void test01(){
Son s;
cout << "Son下的m_A = " << s.m_A << endl;
//如果通过子类对象 访问到父类中同名成员,需要加作用域
cout << "Base下的m_A = " << s.Base::m_A << endl;
}
//同名成员属性处理方式
void test02(){
Son s;
s.func(); //直接调用 调用是子类中的同名成员
//如何调用到父类中同名成员函数?
s.Base::func(); //加入作用域
//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数
//如果想访问到父类中被隐藏的同名成员函数函数,需要加作用域
s.Base::func(100);
}
int main(){
test01();
test02();
}
总结:
子类对象可以直接访问到子类中同名成员
子类对象加作用域可以访问到父类同名成员
当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数
继承同名静态成员处理方式
静态成员和非静态成员出席同名,处理方式一致
-
访问子类同名成员,直接访问即可
-
访问父类同名成员,需要加作用域
-
//继承中的同名静态成员处理方式 class Base{ public: static int m_A; static void func(){ cout << "Base - static void func()" << endl; } static void func(int a){ cout << "Base - static void func(int a)" << endl; } }; int Base::m_A = 100; class Son : public Base{ public: static int m_A; static void func(){ cout << "Son - static void func()" << endl; } }; int Son :: m_A =200; //同名静态成员属性 void test01(){ //1、通过对象访问 cout << "通过对象访问:"<< endl; Son s; cout << "Son 下的 m_A= " << s.m_A << endl; cout << "Base下的m_A=" << s.Base::m_A << endl; //2、通过类名访问 cout << "通过类名访问" << endl; cout << "Son下m_A" << Son :: m_A << endl; //第一个::代表通过类名方式访问 第二个::代表访问父类作用域下 cout << "Base下m_A" << Son :: Base :: m_A << endl; } //同名静态成员函数 void test02(){ //1、通过对象访问 cout << "通过对象访问" << endl; Son s; s.func(); s.Base::func(); //2、通过类名访问 cout << "通过类名访问" << endl; Son::func(); Son::Base::func(); //子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数 //如果想访问父类中被隐藏同名成员,需要加作用域 Son::Base::func(100); } int main(){ test01(); test02(); }
总结:
同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象和通过类名)
继承中的对象模型
//继承中的对象模型
class Base{
public:
int m_A;
protected:
int m_B;
private:
int m_C; //父类中私有的成员属性 是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了
};
class Son : public Base{
public:
int m_D;
};
void test01(){
//父类中所有非静态成员属性都会被子类继承下去
cout << "size of Son=" << sizeof(Son) << endl; //16 四个变量加起来为16
}
int main(){
test01();
}
继承中构造和析构函数
子类继承父类后,当创建子类对象,也会调用父类的构造函数
问题:父类和子类的构造和析构顺序是谁先谁后?
//继承中的构造和析构顺序
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 test01(){
//Base b;
//继承中的构造和析构顺序如下:
//先构造父类,再构造子类,析构的顺序与构造的顺序相反
Son c; //会一并创建父类中的构造和析构函数和对象,先有父类再有子类
}
int main(){
test01();
}
总结:从上面可以看出父类的构造函数先调用、再是子类的构造函数。而析构函数则相反,先是子类的析构函数先调用、再是父类的析构函数。
菱形继承
菱形继承概念:
-
两个派生类继承同一个基类
-
又有某个类同时继承者
-
这种继承被称为菱形继承,或者钻石继承
-
多继承语法
-
C++允许一个类中继承多个类
-
多继承语法:
-
class 子类:继承方式 父类1 , 继承方式 父类2...
⚠️:C++实际开发中不建议使用多继承开发
-
//多继承语法 class Base1{ public: Base1(){ m_A = 100; } int m_A; }; class Base2{ public: Base2(){ m_B = 200; } int m_B; }; //子类 需要继承Base1和Base2 //语法:class 子类:继承方式 父类1 , 继承方式 父类2 class Son : public Base1 , public Base2{ public: Son(){ m_C = 300; m_D = 400; } }; void test01(){ Son s; cout << "sizeof Son = "<< sizeof(s) << endl //当父类中出现同名成员,需要加作用域区分 cout << "Base1::m_A = " <<s.Base1 :: m_A << endl; cout << "Base2::m_A = " <<s.Base2 :: m_A << endl; } int main(){ }
总结:多继承中如果父类中出现了同名情况,子类使用时候要加作用域