C++类的继承与多重继承的访问控制

在前面的练习中我们一直在使用public的继承方式,即共有继承方式,对于protected和private继承方式,即 保护继承 私有继承 方式我们并没有讨论。 
   对于单个类来说,讨论保护继承与私有继承的区别意义是不大的,他们的区别只在多级继承的情况中体现。 

   在这里我声明一下,对于此章节的内容不太适合用过多的文字进行描述,主要还是看例子,通过例子熟悉之间的关系,过多的文字描述会模糊读者思路。 


例程如下(重要部分都做了详细说明): 

//程序作者:管宁 
//站点:www.cndev-lab.com 
//所有稿件均有版权,如要转载,请务必著名出处和作者 

#include <iostream
using namespace std; 

class Base 

public://公有的 
int a1; 
virtual void test() = 0; 
protected://受保护的 
int a2; 
private://私有的 
int a3; 
}; 
//------------------------------------------------------------------------------ 
class ProtectedClass:protected Base//保护继承 

public
void test() 

a1 = 1;//a1在这里被转变为protected 
a2 = 2;//a2在这里被转变为protected 
//a3=3;//错误,派生类不能访问基类的私有成员 

}; 
class ControlProtectedClass:public ProtectedClass//以public方式继承ProtectedClass类 

public
void test() 

a1 = 1;//a1在这里仍然保持为a1在这里被转变为protected 
a2 = 2;//a2在这里仍然保持为a1在这里被转变为protected 
//a3=3;//错误,由于Base类成员为私有的,即使是上级父类是保护继承,也不能改变Base类成员的控制类型 

}; 
//------------------------------------------------------------------------------ 
class PrivateClass:private Base//私有继承 

public
void test() 

a1 = 1;//a1在这里被转变为private 
a2 = 2;//a2在这里被转变为private 
//a3=3;//错误,基类私有成员对文件区域与派生类区域都是不可访问的 

}; 
class ControlPrivateClass:public PrivateClass//以public方式继承PrivateClass类 

public
void test() 

//a1=1;//错误,由于基类PrivateClass为私有继承,a1已经转变为private 
//a2=2;//错误,由于基类PrivateClass为私有继承,a1已经转变为private 
//a3=3;//错误,由于Base类成员为私有的,PrivateClass类也为私有继承 

}; 
//------------------------------------------------------------------------------ 
class PublicClass:public Base//共有继承有区别与其它方式的继承,继承后的各成员不会其改变控制方式 

public
void test() 

a1 = 1;//a1仍然保持public 
a2 = 2;//a2仍然保持protected 
//a3=3;//错误,派生类不能操作基类的私有成员 

}; 
class ControlPublicClass:public PublicClass//以public方式继承PublicClass类 

public
void test() 

a1 = 1;//a1仍然保持public 
a2 = 2;//a2仍然保持protected 
//a3=3;//错误,由于Base类成员为私有成员,即使是上级父类是公有继承,也不能改变Base类成员的控制类型 

}; 
//------------------------------------------------------------------------------ 
int main() 

system("pause"); 



   认真看完了例子,相信细心的读者对于共有继承、保护继承与私有继承的区别与特点已经了解,最后再提醒一下读者,在继承关系中,基类的private成员不但对应用程序隐藏,即使是派生类也是隐藏不可访问的,而基类的保护成员只对应用程序隐藏,对于派生类来说是不隐藏的,保护继承与私有继承在实际编程工作中使用是极其少见的,他们只在技术理论上有意义。

转载,释然读C++ Primer 心中疑惑: http://www.cnblogs.com/harlentan/archive/2011/03/05/2006444.html

关于C++中protected的访问权限的讨论已经是一个很陈旧的话题了,陈旧到大家都不愿意去讨论,觉得他见到到吃饭睡觉那么自然。

我再次读《C++ Primer》的时候,其中关于protected 成员的描述是这样的:

protected Members

The protected access label can be thought of as a blend of private and public :

  • Like private members, protected members are inaccessible to users of the class.
  • Like public members, the protected members are accessible to classes derived from this class.
  • In addition, protected has another important property:
    A derived object may access the protected members of its base class only through a derived object. The derived class has no special access to the protected members of base type objects.

在没有继承的情况下,protected跟private相同。在派生类的时候才出现分化。

上面那段英文前两条都很好理解,基类对象不能访问基类的protected成员,派生类中可以访问基类的protected成员。也就是说private成员是不能被继承的,只有public,protected的成员才可以被继承。

就是最后一条有些迷惑人,派生类对象如果要访问基类protected成员只有通过派生类对象,派生类不能访问基类对象的protected成员。

请注意 drived class和drived object:派生类和派生类对象。第一点和第二点都是针对派生类来说的。

对于第三点总结一句话:只有在派生类中才可以通过派生类对象访问基类的protected成员。

举一个简单的例子:

[cpp]  view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base(){};  
  7.     virtual ~Base(){};  
  8. protected:  
  9.     int int_pro;  
  10. };  
  11. class A : public Base  
  12. {  
  13. public:  
  14.     A(){};  
  15.     A(int da){int_pro = da;}  
  16.     void Print(A &obj){obj.int_pro = 24;}  
  17.     void PrintPro(){cout << "The proteted data is " << int_pro <<endl;}  
  18. };  
  19. int main()  
  20. {  
  21.     A aObj;  
  22.     A aObj2(5);  
  23.     aObj2.PrintPro();  
  24.     aObj.Print(aObj2);  
  25.     aObj2.PrintPro();  
  26.       
  27.          //注释1  
  28.          //aObj.int_pro = 8;  
  29. }  

编译运行结果如下:

The protected data is 5

The protected data is 24

可见,在派生类内部直接访问protected成员和访问派生类对象基类的protected成员都是可行的。

但是若果解开注释1.就会编译报错。

很多书上都说有派生类的情况下protected的访问权限同public。这种说法是不对的,类内部直接访问没什么区别,但是访问对象基类的protected成员只能是在该类的内部。

我这里只列举了只有一层继承的情况,如果有多重继承的情况,比如三层。那么。中间层的类的内部还可以访问第三层类对象的基类成员,但是不能访问第三层类自己的protected的成员。


C++:protected访问说明符

2009-01-23 20:40 jackheroes8383  |  浏览 15825 次
  C++
protected只能被类的成员函数和类的友元函数访问

那子类能不能访问啊?

JAVA的protected是专门设计为让子类访问.
private也可以被类的成员函数和类的友元函数访问 
这个protected到底是为哪种情况设计的啊?
哈哈 protected专门就是为继承(子类)设计的 
用public继承 那么基类所有的访问标识在子类不变 
protected还是protected 
protected只有类本身 和类的子类可以访问,对象是无法访问的! 

除了在继承上 他跟private没有任何区别! 
private 子类也将不能访问!

跟你说了啊~~~  只是在继承上不同 其他都一样的
private无法继承 也就是说子类也不能用基类的 private...
但是protected就是可以的~

明白吗? pravite 只对本类可见 
protected 对本类和继承类可见
提问者评价
感谢
评论(4)  |  95  0

牛比的琭琭 | 七级 采纳率35%

擅长: 电脑/网络 商业/理财

为您推荐:

src="http://entry.baidu.com/rp/home?di=u2115503&rsi0=450&rsi1=25&type=pageembed&version=1&titff=sans-serif%2Ctahoma%2C%22MicrosoftYaHei%22&titfs=14&rss2=%232d64b3&rss3=%232d64b3&title=C%2B%2B%3Aprotected%E8%AE%BF%E9%97%AE%E8%AF%B4%E6%98%8E%E7%AC%A6_%E7%99%BE%E5%BA%A6%E7%9F%A5%E9%81%93&ltu=http%3A%2F%2Fzhidao.baidu.com%2Fquestion%2F83373888.html%3Ffr%3Diks%26word%3DC%252B%252B%2Bprotected%26ie%3Dgbk&ref=http%3A%2F%2Fzhidao.baidu.com%2Fsearch%3Fct%3D17%26pn%3D0%26tn%3Dikaslist%26rn%3D10%26word%3DC%252B%252B%2520protected%26fr%3Dwwwt&pageWidth=1808&pageHeight=846&t=1442672803005&iframeWidth=1808&iframeHeight=846" align="center,center" marginwidth="0" marginheight="0" class="BAIDU_SS_HHIFRAME" scrolling="no" frameborder="0" allowtransparency="true" style="width: 450px; height: 25px; background-color: transparent;">
按默认排序 | 按时间排序

其他1条回答

2009-01-23 20:48 lostman250  | 六级
有这么一条原则:在继承的时候,无论用什么方式(public.protected.private),子类随时都可以访问父类的非private变量或函数。 
所以可以的!

看看这个例程就明白了:http://tech.163.com/05/0407/17/1GOJ25N500091589.html

C++中,类的protected究竟有什么作用?

专业回答
可以叫我表哥    电子产品技术支持  技术部工程师
2015-07-05 11:35
  protected专门就是为继承(子类)设计的 用public继承,基类所有的访问标识在子类不变, protected还是protected 。
  C++编程思想中是这么说的,public意味着随后的定义对所有人都适用;private意味着除了该类型的创建者和该类型的内部成员函数之外,任何人都无法访问这些定义;而protected是继承的类可以访问protected的成员,但不能访问private的成员。

为您推荐:

src="http://entry.baidu.com/rp/home?di=u2115503&rsi0=450&rsi1=25&type=pageembed&version=1&titff=sans-serif%2Ctahoma%2C%22MicrosoftYaHei%22&titfs=14&rss2=%232d64b3&rss3=%232d64b3&title=C%2B%2B%E4%B8%AD%EF%BC%8C%E7%B1%BB%E7%9A%84protected%E7%A9%B6%E7%AB%9F%E6%9C%89%E4%BB%80%E4%B9%88%E4%BD%9C%E7%94%A8%EF%BC%9F_%E7%99%BE%E5%BA%A6%E7%9F%A5%E9%81%93&ltu=http%3A%2F%2Fzhidao.baidu.com%2Fquestion%2F574257523.html%3Ffr%3Diks%26word%3DC%252B%252B%2Bprotected%26ie%3Dgbk&ref=http%3A%2F%2Fzhidao.baidu.com%2Fsearch%3Fct%3D17%26pn%3D0%26tn%3Dikaslist%26rn%3D10%26word%3DC%252B%252B%2520protected%26fr%3Dwwwt&pageWidth=1808&pageHeight=846&t=1442673004018&iframeWidth=1808&iframeHeight=846" align="center,center" marginwidth="0" marginheight="0" class="BAIDU_SS_HHIFRAME" scrolling="no" frameborder="0" allowtransparency="true" style="width: 450px; height: 25px; background-color: transparent;">
错了,不管何种继承,基类的private成员派生类都无法访问,当然也就出现了protected成员,集合了public成员(对派生类) 和 private成员(对外部访问)的特点。
追问:
子类不是可以调用基类public成员么,然后public再调用private, 这样不就调用了基类private了?
 
那基类怎样访问自己的protected呢
追答:
呵呵,public直接调用private的话,所有外部访问全部都能”访问“private了,那private存在的意义是什么?
基类自己的所有数据自己访问是无限制的。
 
OOD的最大特点就是封装和继承,封装也就是外界无法直接访问private和protected成员,只给外界留出了public接口,借由public接口来访问private和proteced成员,用以限制外部访问,就好像你只需要一个遥控器就能控制整个空调的开关,温度的升降而不用去管其内部细节。
而protected存在的意义是当我不想向外部暴露某个函数或者成员变量,但是我又想让派生类知道和访问这个成员,就将其用protected标志,就好比
你爹有两笔存款,一笔是他养老用的,一笔是留给你买房的,养老用的这部分钱你肯定不能拿而且大概你也不知道有多少钱,但是给你买房用的你就可以随便拿,如果你连养老用的这部分钱都拿了那你就是不肖子了,但是你爹可以随便动给你买房的钱(因为钱是他赚的)。当然,不管是养老用的钱还是给你买房用的钱,外人都不能动而且也不知道。
追问:
晕啊 您确定您说的是对的?刚刚有人说,子类是可以间接来访问基类private的
追答:
呵呵,我说的是 “外界无法直接访问private和protected成员” 啊,再把上面的看看吧,这理解起来确实有些困难,可能第一段有误解吧,我只是调侃的说法,意思是你说法中的”调用“和“public调用”是完全不一样的概念,public调用是接口调用,而正常调用是直接调用数据成员。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值