派生类到基类转换的可访问性——新解

C++ primer第四版15.3小节有这样一段话:
如果是 public 继承,则用户代码和后代类都可以使用派生类到基类的转换。

如果类是使用 private 或 protected 继承派生的,则用户代码不能将派生类型对象转换为基类对象

 首先明白:什么是可访问,个人觉得可访问就是可出现。A可以访问B,就说名B可以直接在A中出现。

派生类到基类的转换包括:派生类对象的引用转换为基类对象的引用;派生类对象的指针转换为基类对象的指针;派生类对象转换为基类对象。

//Base.h
#ifndef _BASE_H_
#define _BASE_H_
#include <IOSTREAM>
using namespace std;
class CBase
{
public:
	CBase();
         virtual ~CBase(){};
	CBase(const CBase & b);
	virtual void vir_display() const;
	void Novir_display()const;
private:
	int val;
};
#endif //_BASE_H_


 

//Base.cpp
#include "Base.h"

void CBase::Novir_display() const
{
	cout << "调用CBase的非虚函数" << endl;
}

void CBase::vir_display() const
{
	cout << "调用CBase的虚函数" << endl;
}

CBase::CBase()
{
	val =0;
}

CBase::CBase(const CBase & b )
{
	val = b.val;
}



<pre class="cpp" name="code">//Derived.h
#ifndef _DERIVED_H_
#define _DERIVED_H_
#include "Base.h"
class CDrived : public CBase
{
public:

	CDrived();
	CDrived(const CDrived & d);	

public:
	void Novir_display() const;
	void vir_display() const;
private:
	double data1;
	double data2;
	
};
#endif //_DERIVED_H_
//Derived.cpp
#include "Derived.h"

void CDrived::Novir_display() const
{
	cout << "调用CDrived的非虚函数" << endl;
}

void CDrived::vir_display() const
{
	cout << "调用CDrived的虚函数" << endl;
}

CDrived::CDrived()
{
	
}

CDrived::CDrived( const CDrived & d )
{
	data1 = d.data1;
	data2 = d.data2;
}

//show_main.cpp
#include "Base.h"
#include "Derived.h"
void show_Obj(const CBase b)
{
	b.Novir_display();
	b.vir_display();
}
void show_Ptr(const CBase& b)
{
	b.Novir_display();
	b.vir_display();
}

int main()
{
	CDrived d;
	show_Obj(d);
	show_Ptr(d);

	return 0;
}
实验结果:
 
调用CBase的非虚函数
调用CBase的虚函数
调用CBase的非虚函数
调用CDrived的虚函数
请按任意键继续. . .
解析:
CDrived 继承CBase的方式为public,故上面可以执行。如果,继承方式换成protected,则出现error:“类型转换”: 从“CDrived *”到“const CBase &”的转换存在,但无法访问。因为在show_main.cpp中,CDrived对象转换为CBase对象时需要调用CBase的复制构造函数,而此时CBase的构造函数都变成了protected,在用户代码中无法访问。
对于show_Ptr(d)也出现这个错误,但不是由于调用CBase的复制构造函数产生的,如果声明为void show_Prt(CBase&),则错误为:从“CDrived *”到“CBase &”的转换存在,但无法访问。可见error中的const也跟着消失了。为何会出现这个错误呢?目前没搞懂,求高人赐教。
个人理解:对于private或protected继承,派生类对象中的基类对象部分已经变成private或protected的,故无法在用户代码中访问。
 

再在Derived.h中添加三个函数来制造派生类对象到基类对象的转换,此时CDrived是protected继承方式

void CDrived::dis_Ref(const CBase& b )
{
	b.vir_display();
	b.Novir_display();
}

void CDrived::dis_Obj(const CBase b )
{
	b.vir_display();
	b.Novir_display();
}
void CDrived::test_CDrived()
{//在子类中访问子类转换为基类类型
	CDrived d;
	dis_Ref(d);
	dis_Obj(d);
}


//show_main.cpp

int main()
{
	CDrived d;
         d.test_CDrived();
	return 0;
}

调用CDrived的虚函数
调用CBase的非虚函数
调用CBase的虚函数
调用CBase的非虚函数

可见,protected继承时转换是在派生类中可访问的,即protected继承时,在派生类中派生类到基类的转换是可访问的,在用户代码是不可访问的。

二、如果是 private 继承,则从 private 继承类派生的类不能转换为基类。

先看部分三,然后修改为class CDrived :protected CBase即可,其他不变。结果出现上面的类型转换错误。

三、如果是 protected 继承,则后续派生类的可以访问后续派生类转换为基类类型。

定义class CNext : public CDrived,此时class CDrived :protected CBase。

//Next.h

#ifndef _NEXT_H_
#define _NEXT_H_
#include "Derived.h"
class CNext : public CDrived
{
	
public:
  
	void Novir_display();
	void dis_Ref(const CBase& b);
	void dis_Obj(const CBase b);
	void test_CNext();

	virtual void vir_display() const;

};
#endif //



//Next.cpp

#include "Next.h"

void CNext::Novir_display()
{
	cout << "调用子类的子类的非虚函数" <<endl;
}

void CNext::dis_Ref(const CBase& b )
{
	b.vir_display();
	b.Novir_display();
}
void CNext::dis_Obj( const CBase b )
{
	b.vir_display();
	b.Novir_display();
}
void CNext::test_CNext()
{//在子类的子类中访问子类的子类转换为基类类型
	CNext cn;
	dis_Ref(cn);
	dis_Obj(cn);
}

void CNext::vir_display() const
{
	cout << "调用CNext的虚函数" << endl;
}



 

//show_main.cpp

#include "Base.h"
#include "Derived.h"
#include "Next.h"


int main()
{
	CDrived d;
           d.test_CDrived();
	CNext cn;
	cn.test_CNext();
// 	CBase *pb = new CNext; //failed
//	CDrived * pd = new CNext; //failed

	return 0;
}


实验结果:

调用CDrived的虚函数
调用CBase的非虚函数
调用CBase的虚函数
调用CBase的非虚函数
调用CNext的虚函数
调用CBase的非虚函数
调用CBase的虚函数
调用CBase的非虚函数

可见,在子类的子类CNext中,CNext类型可以转换为基类型CBase。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值