基类与派生类

初学C++的时候,很多人都很头疼各种访问标号下基类与派生类的关系,其实,死记硬背肯定不是一个好的办法,要知道它们之间的关系,先要分析一下访问标号是如何产生的:

在没有继承之前,类的只有两类用户:类本身和类的使用者。把类成员通过public和private划分恰好体现了这一分割:类的使用者只能访问类的public部分,它们一般是类的接口;而类成员则既可以访问public又可以访问private部分,private部分是类的具体实现。当有了继承之后,类的使用者多了一类:基类的派生类。派生类通常要访问基类的一些具体实现,而又不希望让一般的用户访问这些实现,所以就要把这些内容放置在一起,用protected标号来说明。从该类的使用者的角度,protected成员是私有的,你不能访问基类对象的保护成员,但是从该类的继承者的角度,protected则是共有的,因为他可以被继承下来供派生类使用。

为了更进一步限制派生类对基类成员的访问权限,C++又通过访问列表中的访问标号来控制。具体的说

1.如果继承方式为public,那么基类中的public成员在派生类总仍为public,基类中的protected仍为protected,基类中的private在派生类中不能被访问。

2.如果继承方式为protected,那么基类中的public成员在派生类中为protected,基类中的protected成员在派生类中为protected,基类的private成员在派生类中不能被访问。

3.如果继承方式为private,那么基类中的public成员在派生类中为private,基类中的protected成员在派生类中为private,基类的private成员在派生类中不可访问。

总结一下:

基类公有成员基类保护成员基类私有成员
公有继承派生类公有成员派生类保护成员派生类不可访问
保护继承派生类保护乘员派生类保护乘员派生类不可访问
私有继承派生类私有成员派生类私有成员派生类不可访问

再来看一个例子:

//基类
class Base
{
public:
	Base(int i = 0):baseVal_public(i),baseVal_protected(i),baseVal_private(i){}
	int baseVal_public;
	void printVal()
	{
		cout<<baseVal_protected<<endl;
		cout<<baseVal_private<<endl;
	};
protected:
	int baseVal_protected;
private:
	int baseVal_private;

};


//派生类
class Derived_public:public Base
{
public:
	Derived_public(int i = 0):Base(i){}
	
	void getVal()
	{
		//基类的公有成员在派生类中仍未为公有
		cout<<baseVal_public<<endl;
		//基类受保护成员变仍未受保护成员
		cout<<baseVal_protected<<endl;
		//基类的私有成员不能被派生类继承
		//cout<<baseVal_private<<endl;
	}


};


class Derived_protected:protected Base
{
public:
	Derived_protected(int i = 0):Base(i){}
	void getVal()
	{
		//基类的共有成员、受保护成员变为受保护成员
		cout<<baseVal_public<<endl;
		cout<<baseVal_protected<<endl;
		//基类私有成员不能被派生类继承
		//cout<<baseVal_private<<endl;
	}

};

class Derived_private:private Base
{
public:
	Derived_private(int i = 0):Base(i){}
	void getVal()
	{
		//基类的公有成员、受保护成员变为派生类的私有成员
		cout<<baseVal_public<<endl;
		cout<<baseVal_protected<<endl;
		//基类的私有成员不能被继承
		//cout<<baseVal_private<<endl;
	}

};
int main()
{
	
	Base b;
	//公有成员可以被用户访问
	cout<<b.baseVal_public<<endl;
	//私有成员、受保护成员不能被用户访问
	//cout<<b.baseVal_private<<endl;
	//cout<<b.baseVal_protected<<endl;
	//私有成员、受保护成员可以被类成员访问
	b.printVal();

	
	
	//公有继承下
	Derived_public d1;
	//基类的public成员仍为public,可以访问
	cout<<d1.baseVal_public<<endl;
	//私有成员,受保护成员仍为私有、受保护,不能访问
	//cout<<d1.baseVal_protected<<endl;
	//cout<<d1.baseVal_private<<endl;
	d1.getVal();
	
	
	//受保护继承
	Derived_protected d2;	
	//基类的public变为派生类的protected
	//cout<<d2.baseVal_public<<endl;
	//基类的protected变为派生类的protected
	//cout<<d2.baseVal_protected<<endl;
	//基类的private不能被继承
	//cout<<d2.baseVal_private<<endl;
	d2.getVal();

	//私有继承
	Derived_private d3;
	//基类的公有成员、受保护成员变为派生类的私有
	//cout<<d3.baseVal_public<<endl;
	//cout<<d3.baseVal_protected<<endl;
	//私有成员不能被继承
	//cout<<d3.baseVal_private<<endl;
	d3.getVal();
	return 0;
}


程序中,注释起来的代码都是会报错的,报错的原因就在这行代码的上面,这里就不做过多解释了。

当然,虽然你通过访问列表中的访问标号进行了限制,但是总是可以通过在派生类中加一个using声明来恢复它的权限(注意,只能恢复,不能提高)

class Derived_private:private Base
{
public:

	Derived_private(int i = 0):Base(i){}
	void getVal()
	{
		//基类的公有成员、受保护成员变为派生类的私有成员
		cout<<baseVal_public<<endl;
		cout<<baseVal_protected<<endl;
		//基类的私有成员不能被继承
		//cout<<baseVal_private<<endl;
	}

	using Base::baseVal_public1;

};

那就可以

	cout<<d3.baseVal_public1<<endl;

还有一点需要注意的,就会友元关系在继承和派生以后会发生什么变化。

总的来说,分为两点:1.如果一个类被授予为另一个类的友元,它的派生类并不不是这个类的友元2.基类的友元不对基类的派生类不起作用举个例子来说明:

//基类
class Base
{
friend class Frnd;
public:
	Base(int i = 0):baseVal_private(i){}
	
private:
	int baseVal_private;

};

class D1:public Base
{
private:
	int derivedVal;

};

class Frnd
{
public:
	int mem(Base b){return b.baseVal_private;}
	//基类的友元对派生类来说不起作用
	//int mem(D1 d){return d.derivedVal;}

};

class D2:public Frnd
{
public:
	//友元类的派生类不再是授予有缘的那个类的友元
	//int mem(Base b){return b.baseVal_private;}

};

最后有一点需要注意,如果你使用的是class定义的派生类,那么如果不写访问标号,那么默认继承关系为private;如果使用struct定义的派生类,不写访问标号,则默认继承关系为public。
 

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值