您的位置:首页 > 编程语言 > C语言/C++

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: