C++基础之继承与派生
2018-01-03 21:48
176 查看
特别注明:本文章主要参考《C++语言程序设计教程》(第3版)沈显君 杨进才 张勇 编著 *********************************************************初识继承与派生 基类→派生类:派生 派生类→基类:继承 只有一个基类:单继承 有多个基类:多继承(比如一部电影既属于动作类,又属于历史类) 派生类直接吸收了基类的成员,成为了自身的成员,如果想改造基类的 成员,可以通过同名定义的方式进行修改,同名定义,则把继承自基类 的成员屏蔽掉了,如果是函数同名定义,还要注意形参的数目和类型要 相同,否则,系统会认为是重载。 C++中的class默认是private继承,struct默认是public继承 继承是可以传递的,A继承B,B继承C,则A继承了C,所以继承不允许循环。 继承与组合的区别:比如动物中的老虎、狮子、豹子等是组合在一块,而 老虎继承自动物,动物继承自生物 ********************************************************三种继承方式 基类属性 public protected private 继承方式 public public protected 不可访问 protected protected protected 不可访问 private private private 不可访问 如果私有继承之后的派生类作为基类派生下去,其成员将在其派生类中无法访问, 所以私有继承很少使用。 /* 本程序是关于公有继承: */ #include<iostream> using namespace std; const double pi=3.14159; class point{ private: double x,y; public: point(double x,double y){ this->x=x; this->y=y; } void mov(double dx,double dy){ x+=dx,y+=dy; } void show(){ cout<<"("<<x<<", "<<y<<")"<<endl; } }; class circle:public point{ private: double r;//半径 public: circle(double r,double x,double y):point(x,y){ this->r=r; } double area(){ return pi*r*r; } void show_circle(){ cout<<"Center of circle: ";show(); cout<<"Radius: "<<r<<endl; } }; int main() { circle cir(3.0,1,1); cir.show_circle(); cout<<"Area: "<<cir.area()<<endl; cir.mov(6,6); cir.show(); return 0; } //上述程序改为保护继承如下: /* 本程序是关于保护继承 */ #include<iostream> using namespace std; const double pi=3.14159; class point{ protected: double x,y; public: point(double x,double y){ this->x=x; this->y=y; } void mov(double dx,double dy){ x+=dx,y+=dy; } void show(){ cout<<"("<<x<<", "<<y<<")"<<endl; } }; class circle:protected point{ private: double r;//半径 public: circle(double r,double x,double y):point(x,y){ this->r=r; } double area(){ return pi*r*r; } //同名覆盖 void show(){ cout<<"("<<x<<", "<<y<<")"<<endl; } void show_circle(){ cout<<"Center of circle: ";show(); cout<<"Radius: "<<r<<endl; } //同名覆盖 void mov(double dx,double dy){ x+=dx,y+=dy; } }; int main() { circle cir(3.0,1,1); cir.show_circle(); cout<<"Area: "<<cir.area()<<endl; cir.mov(6,6); cir.show(); return 0; } /* 本程序是关于保护继承,可谓是一路保护,圆继承点,圆柱继承圆 */ #include<iostream> using namespace std; const double pi=3.14159; class point{ protected: double x,y; public: point(double x,double y){ this->x=x; this->y=y; } void mov(double dx,double dy){ x+=dx,y+=dy; } void show(){ cout<<"("<<x<<", "<<y<<")"<<endl; } }; class circle:protected point{ protected: double r;//半径 public: circle(double r,double x,double y):point(x,y){ this-&g 4000 t;r=r; } double area(){ return pi*r*r; } void show_circle(){ cout<<"Center of circle: ";show(); cout<<"Radius: "<<r<<endl; } }; class cylinder:protected circle{ protected: double h; public: cylinder(double x,double y,double r,double h):circle(r,x,y){ this->h=h; } double area(){ return pi*r*r*2+2*pi*r*h; } double volume(){ return pi*r*r*h; } void show_cylinder(){ show_circle(); cout<<"Height: "<<h<<endl; } }; int main() { cylinder cy(1,1,6,6); cy.show_cylinder(); cout<<"Total area: "<<cy.area()<<endl; cout<<"Volume: "<<cy.volume()<<endl; return 0; } ******************************************************单继承的构造与析构 /* 单继承的构造与析构,顺序: 1)调用基类构造函数 2)调用内嵌成员对象的构造函数,调用顺序按照他们在类中的定义的顺序 3)派生类自己的构造函数 析构顺序与构造顺序正好相反 */ #include<iostream> using namespace std; class point{ private: int x,y; public: point(int x=0,int y=0){ this->x=x,this->y=y; cout<<"P("<<x<<", "<<y<<") "<<"constructed"<<endl; } ~point(){ cout<<"P("<<x<<", "<<y<<") "<<"destructed"<<endl; } }; class circle:protected point{ private: int r; public: circle(int r,int x,int y):point(x,y){ this->r=r; cout<<"Circle constructed, radius: "<<r<<endl; } ~circle(){ cout<<"Circle destructed, radius: "<<r<<endl; } }; class tube:protected circle{ private: int h; circle cir; public: tube(int h,int r1,int r2,int x,int y):cir(r1,x,y),circle(r2,x,y){ this->h=h; cout<<"Tube constructed, height: "<<h<<endl; } ~tube(){ cout<<"Tube destructed, height: "<<h<<endl; } }; int main() { tube tu(1,2,3,4,5); return 0; } 运行结果如下: P(4, 5) constructed Circle constructed, radius: 3 P(4, 5) constructed Circle constructed, radius: 2 Tube constructed, height: 1 Tube destructed, height: 1 Circle destructed, radius: 2 P(4, 5) destructed Circle destructed, radius: 3 P(4, 5) destructed Process returned 0 (0x0) execution time : 0.219 s Press any key to continue. *****************************************************类型兼容 1)派生类对象可以赋值给基类对象 2)派生类对象可以初始化基类的引用 3)基类的指针可以指向派生类 经过实验我发现:虽然可以按照上面那么做,但是基类却访问不了派生类中 新增加的成员(基类中不存的成员) *****************************************************多继承的构造与析构 1)调用各基类的构造函数,各基类构造函数的调用顺序按照基类被继承时的声明的顺序 从左到右依次进行 2)调用内嵌成员对象的构造函数,成员对象的构造函数的调用顺序按照他们在类中 定义的顺序依次进行 3)调用派生类的构造函数 析构顺序正好和构造顺序相反 ******************************************************多继承的二义性 由于一个派生类有多个基类,这多个基类中可能存在相同的函数定义,当调用这样 的函数时,系统不知道调用哪一个。怎么办? 方案1)就自己换个名重新定义具有相同功能的函数。 方案2)给出作用域,比如某派生类继承了两个类p1,p2,而p1,p2均有show()函数, 如果调用show()函数,可以这样调用,p1::show(),p2::show(),或者自己再重新 定义个show函数吧吧 ******************************************************多继承的间接二义性 假设a继承了b,c,d,而b,c,d又都继承了e,那么b,c,d都拥有了e的成员,进一步,a 拥有了b,c,d的所有成员,那么a拥有了三份完全相同的e的成员,如果用a调用e中的成 员,显然系统不知道调用哪一个了,怎么办?还是可以通过给出作用域或者重新定义 功能相同的别名函数来解决这个问题,但是这也比较麻烦吧!于是引入了虚基类,虚基 类的目的就是把上述所说的三份完全相同的e中的成员搞成只有一份,从而避免了二义性。 ******************************************************虚基类 虚基类的构造与析构 虚基类定义了带参数的构造函数的时候,所有派生类都必须在构造函数的初始化列表中 对虚基类初始化,但只有最远派生类的构造函数调用虚基类的构造函数。 /* 本程序中涉及多继承关系是:car和wagon都继承automobile, car_wagon继承了car和wagon,本程序通过给出作用域解决二义性问题 */ #include<iostream> using namespace std; class automobile{ private: int power; public: automobile(int power){ this->power=power; } void show(){ cout<<"power: "<<power<<endl; } }; class car:public automobile{ private: int seat; public: car(int power,int seat):automobile(power){ this->seat=seat; } void show(){ cout<<"car: "; automobile::show(); cout<<"seat: "<<seat<<endl; } }; class wagon:public automobile{ private: int load; public: wagon(int power,int load):automobile(power){ this->load=load; } void show(){ cout<<"wagon: "; automobile::show(); cout<<"load: "<<load<<endl; } }; class car_wagon:public car,public wagon{ public: car_wagon(int c_power,int w_power,int seat,int load):wagon(w_power,load),car(c_power,seat){} void show(){ cout<<"car_wagon: "<<endl; car::show(); wagon::show(); } }; int main() { car_wagon cw(150,500,5,20); cw.show(); return 0; } /* 本程序来使用虚基类,并研究其构造和析构情况 本程序中涉及多继承关系是:car和wagon都继承automobile, car_wagon继承了car和wagon,本程序使用虚基类,可以避免二义性问题,还 可以减少内存空间(基类只有一份被继承)。 注意:所有派生类都必须在构造函数的初始化列表中对虚基类初始化 */ #include<iostream> using namespace std; class automobile{ private: int power; public: automobile(int power){ this->power=power; cout<<"automobile constructed"<<endl; } void show(){ cout<<"power: "<<power<<endl; } }; class car: virtual public automobile{ private: int seat; public: car(int power,int seat):automobile(power){ this->seat=seat; cout<<"car constructed"<<endl; } void show(){ cout<<"car: "; automobile::show(); cout<<"seat: "<<seat<<endl; } }; class wagon: virtual public automobile{ private: int load; public: wagon(int power,int load):automobile(power){ this->load=load; cout<<"wagon constructed"<<endl; } void show(){ cout<<"wagon: "; automobile::show(); cout<<"load: "<<load<<endl; } }; class car_wagon:public car,public wagon{ public: car_wagon(int c_power,int w_power,int seat,int load):wagon(w_power,load), car(c_power,seat),automobile(c_power){cout<<"car_wagon constructed"<<endl;} void show(){ cout<<"car_wagon: "<<endl; car::show(); wagon::show(); } }; int main() { car_wagon cw(150,500,5,20); cw.show(); return 0; }
相关文章推荐
- C++学习6-面向对象编程基础(运算符重载、类的派生与继承、命名空间)
- C++基础:继承与派生(声明 继承方式 访问规则)
- (C++基础)浅谈继承与派生
- c++基础(继承与派生)
- C++基础(十)继承与派生——多重继承
- C++基础(九)继承与派生——派生类成员的构造函数和析构函数
- c++基础10:继承和派生 虚函数的作用 多态性概念 纯虚函数和抽象类的概念
- 【c++语言基础】浅析C++继承与派生
- 关于C++程序设计的基础核心之二:继承与派生的基本知识
- 【C++学习笔记】继承与派生基础概念
- C++基础——继承与派生
- 【C++学习笔记】继承与派生基础概念
- C++基础(八)继承与派生——派生类成员的访问属性
- C/C++基础知识总结——继承与派生
- Python基础-继承与派生
- C++语言基础 例程 继承与组合
- C++继承与派生详解:C++派生类声明和构成、继承的意义
- C++基础知识整理四(构造函数及继承)
- C++继承与派生
- c++第四次作业 继承和派生