赞
踩
继承:面向对象的三大特性之一
使用例子模拟实现的方法来理解更加容易:
模拟一个学习网页的页面
一个网站有很多的网页,每个网页有相同的部分和不同的部分
各个网页相同的部分可以采用继承的方法来写,这样就避免了写重复的代码
首先来看看 不采用 继承 技术来写的代码-----超级菜鸟级别:
#include<iostream> using namespace std; //逻辑上,模拟写一个网站 //网站有多个页面: //页面一:C++ 页面 class Cpp { public: //页面的公共部分: //页眉部分 void Header() { cout << "首页 番剧 直播 游戏中心 会员购 漫画 赛事" << endl; } //底部部分 void Bottomer() { cout << "评论 联系方式 投诉" << endl; } //左侧部分 void lefter() { cout << "CPP Java Python" << endl; } public: //CPP页面独有部分 void Viodeo() { cout << "C++一天速成 C++实战项目" << endl; } }; //CPP页面的链接入口 void enterCPP() { cout << "-----------------------CPP-------------------------" << endl; Cpp c; c.Bottomer(); c.Header(); c.lefter(); c.Viodeo(); cout << endl; cout << endl; } //页面二:Java 页面 class Java { public: //页面的公共部分: //页眉部分 void Header() { cout << "首页 番剧 直播 游戏中心 会员购 漫画 赛事" << endl; } //底部部分 void Bottomer() { cout << "评论 联系方式 投诉" << endl; } //左侧部分 void lefter() { cout << "CPP Java Python" << endl; } public: //CPP独有部分 void Viodeo() { cout << "Java一天速成 Java实战项目" << endl; } }; //Java页面的链接入口 void enterJava() { cout << "-----------------------Java-------------------------" << endl; Java j; j.Bottomer(); j.Header(); j.lefter(); j.Viodeo(); cout << endl; cout << endl; } //页面三:Python 页面 class Python { public: //页面的公共部分: //页眉部分 void Header() { cout << "首页 番剧 直播 游戏中心 会员购 漫画 赛事" << endl; } //底部部分 void Bottomer() { cout << "评论 联系方式 投诉" << endl; } //左侧部分 void lefter() { cout << "CPP Java Python" << endl; } public: //Python独有部分 void Viodeo() { cout << "Python一天速成 Python实战项目" << endl; } }; //Python页面的链接入口 void enterPython() { cout << "----------------------Python------------------------" << endl; Python p; p.Bottomer(); p.Header(); p.lefter(); p.Viodeo(); cout << endl; cout << endl; } int main() { //模拟点击 C++链接 enterCPP(); //模拟点击 Java链接 enterJava(); //模拟点击 Python链接 enterPython(); return 0; }
运行结果:
继承的优点:减少重复代码
基本语法:
class A: public B
A 为子类或者称为派生类
B 为父类或者称为基类
public 继承方式(有很多种)
即:
class 子类:继承方式 基类
//采用继承的技术来写: #include<iostream> using namespace std; //公共页面: class BasePage { public: //页面的公共部分: //页眉部分 void Header() { cout << "首页 番剧 直播 游戏中心 会员购 漫画 赛事" << endl; } //底部部分 void Bottomer() { cout << "评论 联系方式 投诉" << endl; } //左侧部分 void lefter() { cout << "CPP Java Python" << endl; } }; class CPP : public BasePage { public: //CPP独有部分 void Viodeo() { cout << "C++一天速成 C++实战项目" << endl; } }; class Java : public BasePage { public: //Java独有部分 void Viodeo() { cout << "Java一天速成 Java实战项目" << endl; } }; class Python : public BasePage { public: //Python独有部分 void Viodeo() { cout << "Python一天速成 Python实战项目" << endl; } }; //CPP页面的链接入口 void enterCPP() { cout << "-----------------------CPP-------------------------" << endl; CPP c; c.Bottomer(); c.Header(); c.lefter(); c.Viodeo(); cout << endl; cout << endl; } //Java页面的链接入口 void enterJava() { cout << "-----------------------Java-------------------------" << endl; Java j; j.Bottomer(); j.Header(); j.lefter(); j.Viodeo(); cout << endl; cout << endl; } //Python页面的链接入口 void enterPython() { cout << "----------------------Python------------------------" << endl; Python p; p.Bottomer(); p.Header(); p.lefter(); p.Viodeo(); cout << endl; cout << endl; } int main() { //模拟点击 C++链接 enterCPP(); //模拟点击 Java链接 enterJava(); //模拟点击 Python链接 enterPython(); return 0; }
运行结果:
三种继承方式:
1、公共继承
2、保护继承
3、私有继承
实际上对应的是类中的三种访问权限
//代码示例: #include<iostream> using namespace std; //1、公共继承示例: //父类1: class Base1 { public: int m_public_A; protected: int m_protected_A; private: int m_private_A; }; //继承1 class son1:public Base1 { public: void func() { m_public_A = 10;//(公共继承的情况下)父类中的公共权限,子类中依然为公共权限 m_protected_A = 10;//(公共继承的情况下)父类中的保护权限,子类中依然为保护权限 //m_private_A = 10;// err (公共继承的情况下)父类中的私有权,子类不可访问 } }; //测试(对继承中的结论进行验证) void test1() { son1 s1; s1.m_public_A = 10;//m_public_A 在父类子类中都是公共权限,类外可以访问 //s1.m_protected_A = 10;// err m_protected_A 在父类和子类中都是保护权限,类外不可以访问 } //2、保护继承示例: //父类2: class Base2 { public: int m_public_A; protected: int m_protected_A; private: int m_private_A; }; //继承2 class son2 :protected Base2 { public: void func() { m_public_A = 10;//(保护继承的情况下)父类中的 公共权限,子类中变为 保护权限 m_protected_A = 10;//(保护继承的情况下)父类中的 保护权限,子类中依然为 保护权限 //m_private_A = 10;// err (保护继承的情况下)父类中的私有权,子类不可访问 } }; //测试(对继承中的结论进行验证) void test2() { son2 s2; //s2.m_public_A = 10;//err m_public_A 在子类中都是保护权限,类外不可以访问 //s2.m_protected_A = 10;// err m_protected_A 在父类和子类中都是保护权限,类外不可以访问 } //3、私有继承示例: //父类3: class Base3 { public: int m_public_A; protected: int m_protected_A; private: int m_private_A; }; //继承3 class son3 :private Base3 { public: void func() { m_public_A = 10;//(私有继承的情况下)父类中的 公共权限,子类中变为 私有权限 m_protected_A = 10;//(私有继承的情况下)父类中的 保护权限,子类中变为 私有权限 //m_private_A = 10;// err (私有继承的情况下)父类中的私有权,子类不可访问 } }; //测试(对继承中的结论进行验证) void test3() { son3 s3; //s3.m_public_A = 10;//err m_public_A 在子类中都是私有权限,类外不可以访问 //s3.m_protected_A = 10;// err m_protected_A 在父类中是保护权限, // 在子类中是私有权限,类外不可以访问 } int main() { test1(); test2(); test3(); return 0; }
核心要点:在继承之中,子类会将父类中所有的非静态变量继承
代码验证:
#include<iostream> using namespace std; //写一个父类: class Base { public: int m_A; protected: int m_B; private: int m_C; }; //写一个子类: class son:public Base { public: int m_D; }; void test() { //打印输出一下子类类型的大小: cout << "size of son = " << sizeof(son) << endl; //打印结果为 16 = 4 * 4 //即 4 个 int 型变量的大小 //注:子类会继承父类的私有权限下的变量, // 但是编译器将它隐藏了,子类无法访问 } int main() { test(); return 0; }
结果:
使用 vs 的工具 Developer command prompt 可以验证上述结论,这里不进行演示。
在父类中:
先调用构造函数,
之后调用析构函数
在子类中:
先调用父类的构造函数
再调用子类的构造函数
再调用子类的析构函数
再调用子类的析构函数
代码演示:
#include<iostream> using namespace std; //写一个父类: class Base { public: Base() { cout << "父类中 构造函数 的调用" << endl; } ~Base() { cout << "父类中 析构函数 的调用" << endl; } }; //采用继承写一个子类: class son :public Base { public: son() { cout << "子类中 构造函数 的调用" << endl; } ~son() { cout << "子类中 析构函数 的调用" << endl; } }; //测试案例: void test01() { cout << "--------------父类----------------" << endl; Base b; cout << endl; } void test02() { cout << "--------------子类----------------" << endl; son s; cout << endl; } int main() { test01(); test02(); return 0; }
结果:
问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?
访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
代码示例:
#include<iostream> using namespace std; //创建父类: class Base { public: int m_A = 10; public: void func1() { cout << "Base'func1()" << endl; } }; //创建一个子类 class son:public Base { public: int m_A = 100; public: void func1() { cout << "son'func1()" << endl; } }; void test01() { cout << "-----------直接访问子类------------" << endl; //直接访问子类得到的是子类本身的变量和函数: son s; cout << "son'm_A = " << s.m_A << endl;//结果:100 s.func1();// 结果:"son'func1()" } void test02() { cout << "----------通过子类访问父类-----------" << endl; //要想访问子类继承到的父类的变量和函数,需要加一个 作用域 son s; cout << "Base'm_A = " << s.Base::m_A << endl;//结果:100 s.Base::func1();//结果:"Base'func1()" } int main() { test01(); test02(); return 0; }
结果:
同名静态成员的处理本质上和非静态同名成员的处理相同,
有所不同的仅仅是多了一种使用 类名 访问的技术
同名成员有同名成员变量和同名成员函数,两者处理方式相同
代码示例:
#include<iostream> using namespace std; //写一个父类: class Base { public: //静态变量: //静态变量作为成员变量,类内声明,类外初始化 static int m_A; public: //静态成员函数: static void func() { cout << "\tBase'func()" << endl; } }; //初始化: int Base::m_A = 10; //写一个子类,继承上面的父类: class son: public Base{ public: //与父类同名的静态变量: static int m_A; public: //静态成员函数: static void func() { cout << "\tson'func()" << endl; } }; //初始化: int son::m_A = 20; void test01() { cout << "--------静态成员变量---------" << endl; cout << endl; //1、通过对象访问: cout << "通过对象访问:" << endl; son s;//创建一个对象 //与非静态同名成员变量的访问相同: //子类自己的静态变量直接访问即可: cout << "\tson'm_A = " << s.m_A << endl;// 结果:son'm_A = 20 //通过子类访问父类的静态成员变量需要加一个作用域: cout << "\tBase'm_A = " << s.Base::m_A << endl;// 结果:Base'm_A = 10 cout << endl; //2、通过类名访问: cout << "通过类名访问:" << endl; cout << "\tson'm_A = " << son::m_A << endl;// 结果:son'm_A = 20 //第一个 :: 是指通过类名访问,第二个 :: 是指访问父类的作用域 cout << "\tBase'm_A = " << son::Base::m_A << endl;// 结果:Base'm_A = 10 cout << endl; } void test02() { cout << "---------静态成员函数----------" << endl; cout << endl; //1、通过对象访问: cout << "通过对象访问:" << endl; son s; //直接访问 得到的是子类中的静态成员函数 s.func();//结果:son'func() //通过作用域可以访问 父类下的静态成员函数 s.Base::func();//结果:Base'func() cout << endl; //2、通过类名访问: cout << "通过类名访问:" << endl; son::func(); //第一个 :: 的含义是通过类名访问,第二个 :: 的含义是作用域 son::Base::func(); } int main() { test01(); test02(); return 0; }
在实际的开发中一般不建议使用多继承,出现同名成员处理比较麻烦
语法:
class 子类 : 继承方式 父类1 , 继承方式 父类2 , …
代码示例:
#include<iostream> using namespace std; //写一个父类1: class Base1 { public: Base1() { m_A = 10; } int m_A; }; //写一个父类2: class Base2 { public: Base2() { m_B = 20; } int m_B; }; //写一个子类,继承父类1、父类2 class son :public Base1, public Base2 { public: son() { m_C = 30; m_D = 40; } int m_C; int m_D; }; void test01() { //son 继承了两个父类的所有的变量 //加上 son 自身的两个变量,一共 4 个 int 型变量 cout << "size of son is " << sizeof(son) << endl;//结果为: size of son is 16 } int main() { test01(); return 0; }
什么叫菱形继承?
一个父类被两个子类继承,
这两个子类又作为父类被一个新的子类继承,
这种继承模型被称为菱形继
代码示例:
写一个动物类
让动物类被马类继承
同时,让动物类被驴类继承
最后让骡类继承驴类和马类
#include<iostream> using namespace std; //动物类: class Animal { public: int m_age; }; //马类: class horse :public Animal{}; //驴类 class donkey :public Animal{}; //骡类 class mule :public horse, public donkey{}; void test01() { //测试 mule 的大小: // mule 分别从两个父类中继承了一个 int 型变量,因此一共有两个 int 型变量 cout << "size of mule is " << sizeof(mule) << endl;// 8 mule m; //未使用关键字 virtual 写成 m.m_age = 10; 会导致不明确 //因此改写成: m.horse::m_age = 10; m.donkey::m_age = 20;//必须添加一个作用域 //打印测试: cout << "mule'horse'm_age is " << m.horse::m_age << endl; cout << "mule'donkey'm_age is " << m.donkey::m_age << endl; } int main() { test01(); return 0; }
结果:
//不采用 virtual 写法的代码: #include<iostream> using namespace std; //动物类: class Animal { public: int m_age; }; //马类: //相比之前的代码,这里这里添加了 virtual 变成了虚继承 class horse :virtual public Animal {}; //驴类 //同样 这里这里添加了 virtual 变成了虚继承 class donkey :virtual public Animal {}; //骡类 class mule :public horse, public donkey {}; void test01() { //测试 mule 的大小: // mule 中有两个指针指向一块 int 型变量空间,一共 3*4 bit cout << "size of mule is " << sizeof(mule) << endl;// 12 mule m; //使用关键字 virtual,不会导致指代不明确 m.m_age = 9; m.horse::m_age = 10; m.donkey::m_age = 20;//必须添加一个作用域 //打印测试: cout << "mule'm_age is " << m.m_age << endl;//20 cout << "mule'horse'm_age is " << m.horse::m_age << endl;//20 cout << "mule'donkey'm_age is " << m.donkey::m_age << endl;//20 //说明 :使用了 virtual 会使得所有的 m_Age 为一块空间 }![在这里插入图片描述](https://img-blog.csdnimg.cn/80ba838ff2b44729a4796b1b4d0f011f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56CB5oGp,size_20,color_FFFFFF,t_70,g_se,x_16) int main() { test01(); return 0; }
结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。