继承的三种方式与派生类的构造函数和析构函数~

一:继承的三种方式

形式:

class 派生类名:继承方式  基类名,继承方式  基类名,继承方式  基类名·····


①公有继承(public 类名)

1.在派生类中基类的公有成员和受保护的成员在派生类中仍然是公有成员和受保护的成员。私有成员不可见,所以派生类的成员函数也不可以直接访问基类的私有成员,要通过基类的成员函数这个接口。

2.如果派生类中某一基类同名的成员函数的实现与基类不同,那么就要在派生类里重新定义一下,这样在派生类中就会屏蔽或者说覆盖掉了基类同名的成员函数。


②私有继承(private 类名)

1.基类的非私有成员全部变成派生类的私有成员,派生类的对象都不可以直接访问基类的成员函数和数据成员。基类的私有成员对于派生类仍然不可见,要通过基类成员函数这个接口去访问,但是呢,就像刚才说的,派生类的对象是没有办法直接调用基类的成员函数的。

再通过下面这个代码好好去理解一下上面说的基类的成员函数私有继承后对象不能访问,以及如何去访问到基类的成员函数的方法(在派生类中定义一个函数,然后return 基类名::函数名();)

#include
    
    
     
     
using namespace std;
#include
     
     
      
      
#define PI 3.14159
class circle
{
public:
	circle(int r){ radius = r; }; //这里为什么我要把构造函数定义成有参构造函数,而不是默认构造函数,这个是有道理的,下面派生类那里去解释
	~circle(){};
	int Getradius(void);
private:
	int radius;
};
class cylinder :private circle
{
public:
	cylinder(int r, int h) :circle(r), height(h){};  //因为radius是基类的私有成员,在派生类里不可见,所以就不可以在初始化列表里出现radius(r)
	//所以说我们只能借助于基类的构造函数去访问私有成员,于是乎我们需要在基类的构造函数中传一个参数,故我们把基类的构造函数定义成了有参构造函数。
	//这样就可以在初始化列表里调用基类的构造函数去初始化radius
	int GetHeight(void);
	int Getradius(void);//就是为了解决私有继承后带来对象不能访问这个函数的问题,在派生类中定义一个同名函数,会覆盖基类的Getradius
	double GetArea(void);
	double GetVolum(void);
private:
	int height;
};
int main(void)
{
	cylinder a(2, 3);
	a.Getradius();  //访问的是派生类定义Getradius()
	cout << "半径为:" << a.Getradius() << endl;
	cout << "高度为:" << a.GetHeight() << endl;
	cout << "面积为:" << a.GetArea() << endl;
	cout << "体积为:" << a.GetVolum() << endl;
	system("pause");
	return 0;
}
int circle::Getradius(void)
{
	return radius;
}
int cylinder::GetHeight(void)
{
	return height;
}
int cylinder::Getradius(void)
{
	return circle::Getradius(); //使用作用域限定符表明调用的是基类的同名函数
}
double cylinder::GetArea(void)
{
	return 2 * PI*Getradius()*height;
	//这里调用的都是派生类自己定义的Getradius函数,基类的被覆盖掉了,只有基类名::Getradius()才能够访问到基类的这个函数
}
double cylinder::GetVolum(void)
{
	return PI*Getradius()*Getradius()*height;
}


     
     
    
    


2.派生类再往下派生,基类的所有东西都对其派生类不可见了。

③保护继承

1.基类的非私有成员在派生类中是受保护的成员,基类的私有成员在派生类中不可见。

2.保护继承有什么好处?

——既可以实现成员的隐藏,不破坏封装性,又可以方便类家族中派生类逐层去继承基类的成员,不会出现像私有继承“第三代”的时候,“爷爷类”的东西完全看不到的情况。


二:派生类的构造函数与析构函数

派生类不能继承基类的构造函数和析构函数,必须自己定义,由于派生类和基类的特殊关系,在设计派生类的构造函数时,不仅要考虑到派生类新增的数据成员,也应该考虑到基类的数据成员的初始化。

派生类构造函数初始化的顺序:基类的数据成员,派生类的子对象,派生类的数据成员

1.如果基类的构造函数是无参构造函数或者默认构造函数,那么派生类初始化方式如下面的代码所示:

class circle
{
public:
	circle(){}; 
	~circle(){};
protected:
	int radius;
};
class cylinder :private circle
{
public:
	cylinder(int r, int h) : height(h){ radius = r; };//radius不能在初始化列表里初始化,只能在函数体里赋值
	                                                   //初始化列表只能接受三种东西,基类的构造函数,自己的子对象,自己的数据成员
	                                 //而radius是基类的数据成员,有没有通过构造函数的方式初始化,所以它不可以在初始化列表中初始化
private:
	int height;
};
2.如果基类的构造函数有参数时,那么派生类初始化方式如下面的代码所示:
class circle
{
public:
	circle(int r):radius(r){}; 
	~circle(){}; 
protected:
	int radius;
};
class cylinder :private circle
{
public:
	cylinder(int r, int h) : circle(r),height(h){};//在初始化列表里按照初始化顺序先调用基类的构造函数
private:
	int height;
};
3.如果派生类含有子对象,那么派生类初始化方式如下面的代码所示:

class birthiday
{
public:
	birthiday(int y, int m, int d) :year(y), month(m), day(d){};
protected:
	int year;
	int month;
	int day;
};
class person
{
public:
	person(int num, int y, int m, int d) :day(y, m, d), number(num){};
private:
	int number;
	birthiday day;//子对象
};

派生类析构函数调用的顺序:派生类的析构函数,子对象的析构函数,基类的析构函数

析构函数没有参数,系统会自动调用,所以派生类只要做好自己的析构函数就好,不用管基类和子对象的析构函数。

#include
    
    
     
     
using namespace std;
#include
     
     
      
      
class A
{
public:
	A(){ cout << "调用A的构造函数" << endl; };
	~A(){ cout << "调用A的析构函数" << endl; };
};
class B :public A
{
public:
	B(){ cout << "调用B的构造函数" << endl; };
	~B(){ cout << "调用B的析构函数" << endl; };
};
int main(void)
{
	B b;
	system("pause");
	return 0;
}
/*
显示结果为:
调用A的构造函数
调用B的构造函数
调用B的析构函数
调用A的析构函数
*/
     
     
    
    









  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值