继承与多态
来源:互联网 发布:红马后一计划软件 编辑:程序博客网 时间:2024/06/06 09:19
继承:
保护已有类的特性而构造新类的过程称为继承
在已有类的基础上新增自己的特性而产生新类的过程称为派生
被继承的已有类称为基类(或父类);
派生出的新类称为派生类(或子类);
继承的目的:实现代码重用
派生的目的:当新的问题出现,原有程序无法解决时,需要对原有程序进行改造
三种继承方式:
公有继承,
私有继承,
保护继承。
1:当基类有默认构造函数时,当创建派生类的对象时,派生类的构造函数会自动调用基类的构造函数
2:当激烈没有默认构造函数时,派生类的构造函数必须使用初始化参数列表来调用基类的构造函数
3:在构造子类对象时,先执行父类构造对象,然后执行参数类的构造函数,最后执行子类构造函数。
例:
#include<iostream>using namespace std;class Father{ protected:int f_data; public:Father(int x):f_data(x){}Father(){f_data=1;}};class Son:public Father <span style="color:#ff6666;"> </span><span style="color:#ff0000;"> //以public继承</span>{ private:int s_data; public:Son(int x):s_data(x){}Son(){s_data=11;}void show(){ cout<<"f_data:"<<f_data<<endl; <span style="color:#ff0000;">//打印继承父类的id</span> cout<<"s_data:"<<s_data<<endl; }};int main(){ Son s1; s1.show(); return 0;}
赋值兼容规则:
派生类对象可以赋值给基类对象 (比如要动物我们可以给猴子)
派生类对象可以初始化基类引用
派生类对象的地址可以赋值给指向基类的指针(放动物的地方我们可以放猴子)
#include<iostream>using namespace std;class A{ public:void show(){ cout<<"A"<<endl;}};class B:public A{ public:void show(){ cout<<"B"<<endl;}};class C:public B{ public:void show(){ cout<<"C"<<endl;}};void fun(A* ptr){ ptr->show();}int main(){ A a1,*p; <span style="color:#ff0000;">//通过指针指向,指针首先指向其继承部分,所以一直打印:A</span> B b1; C c1; p=&a1; fun(p); <span style="color:#ff0000;"> //显示为:A</span> p=&b1; fun(p); <span style="color:#ff0000;">//显示为:A</span> p=&c1; fun(p); <span style="color:#ff0000;"> //显示为:A</span> return 0;}
多态:
c++多态是通过虚函数实现的,虚函数允许子类重新定义成员函数,而子类重写定义弗雷接口的做法成为覆盖或重写
子类需要公有继承父类
定义父类的指针或引用,然后通过指针或引用去调用相应的虚函数
虚函数:
成员函数之前加上virtual 关键字,就是虚成员函数。
判断是否为虚函数:
1:该函数与基类的虚函数有相同的函数名
2:该函数与基类的虚函数有相同的残苏个数与对应的参数类型
3:该函数与基类虚函数有相同的返回值或者满足赋值兼容规则的指针,引用的返回值
#include<iostream> using namespace std;class A{ public: virtual void show() <span style="color:#ff0000;">//虚成员函数</span>{ cout<<"A"<<endl;}};class B:public A{ public:void show()<span style="color:#ff0000;">//虚成员函数</span>{ cout<<"B"<<endl;}};class C:public B//虚成员函数{ public:void show(){ cout<<"C"<<endl;}};void fun(A* ptr){ ptr->show();}int main(){ A a1,*p; <span style="color:#ff0000;">//通过虚函数,重写父函数</span> B b1; C c1; p=&a1; fun(p); <span style="color:#ff0000;"> //显示为:A</span> p=&b1; fun(p); <span style="color:#ff0000;">//显示为:B</span> p=&c1; fun(p); <span style="color:#ff0000;"> //显示为:C</span> return 0;}
多态与非多态区别:
区别就是地址是早绑定还是晚绑定,如果函数的调用在编译期间就可以确定函数的调用地址,并产生代码,就是静态的也就是早绑定是非多态的。而如果函数的调用地址不能在编译期间确定,需要在运行时才确定,这就是晚绑定也称动态联编,是多态的
重载与重写区别:
重载overload:函数名相同,参数列表不同,在同类内部存在,不以返回值判断
重写overwrrte:也称为覆盖,子类重新定义父类中的同名函数。函数特征相同,单数具体实现不同,基类的函数要有关键字virtual,主要是在继承关系中出现。
组合和继承:
组合是has,继承是is,比如眼睛,猴子适合于组合,而动物,猴子适合用继承。
虚拟继承:
沙发:可以看电视,有重量
床:可以睡觉,有重量
沙发床:继承沙发和床,既可以睡觉,又可以看电视sleeper_sofa:public bed,public sofa //出错,沙发床不能有两个重量
所以先把重量定义为一类,然后沙发和床都虚拟继承该类。
#include<iostream>using namespace std;class Furniture{ int weight; public: Furniture(){cout<<"Furniture()"<<endl;} ~Furniture(){cout<<"~Furniture()"<<endl;} void setweight(int x) {weight=x; } void getweight() {cout<<weight<<endl; }};class Sofa:<span style="background-color: rgb(255, 204, 0);">virtual</span> public Furniture{ public:Sofa(){cout<<"Sofa()"<<endl;}~Sofa(){cout<<"~Sofa()"<<endl;}void watch_tv(){ cout<<"watch_tv"<<endl;}};class Bed:<span style="background-color: rgb(255, 255, 0);">virtual</span> public Furniture{ public:Bed(){cout<<"Bed()"<<endl;}~Bed(){cout<<"~Bed()"<<endl;}void sleep(){ cout<<"sleeping"<<endl;}};class Sleepersofa:public Bed,public Sofa{ public:Sleepersofa(){cout<<"Sleepersofa()"<<endl;}~Sleepersofa(){cout<<"~Sleepersofa()"<<endl;}void Foldout(){ cout<<"Fold out the sofa"<<endl;}};int main(){ Sleepersofa s1; s1.setweight(20); s1.getweight(); cout<<endl;}skywalker@skywalker:~/item$ ./a.out <span style="white-space:pre"><span style="color:#cc0000;"></span></span><span style="color:#cc0000;">//结果如下</span>Furniture()Bed()Sofa()Sleepersofa()20~Sleepersofa()~Sofa()~Bed()~Furniture()
构造对象的规则需要扩展以控制多重继承。构造函数按下列顺序被调用:
1:任何虚拟基类的构造函数按照它们被继承的顺序构造
2:任何非虚拟基类的构造函数按照它们被继承的顺序构造;
3:任何成员对象的构造函数按照它们声明的顺序调用;
4:类自己的构造函数。
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 继承与多态
- 多态与继承
- 继承与多态
- 版本控制系统(VCS→DVCS)
- 取得数据库某个表的最大id 可以用以下方法
- HDOJ 5463 Clarke and minecraft(贪心向上取整)
- Fragment,Spinner,viewPager,Bundle,返回(请求码,结果码)
- 一步一步做一个linux文件传输软件(四)
- 继承与多态
- JavaScript基础(上)
- 自己去设计es的分片数量安排的方法--Capacity Planning--es横向扩展设计
- inline-block之后意外发现块下沉
- oracle比较常用的sql
- 【ecmall】安装成功后无法访问前后台的问题
- [随手记]Java替换<br />标签
- VIM 插件安装
- Error creating bean with name 'org.apache.cxf.binding.soap.customEditorConfigurer'