C++继承(public/protected/private)

继承

谈到继承就不能不先说说public,protected,private:

(1) Public成员:

1.      在类内部:可直接使用,可以通过(类的对象,指针,引用------以后称之为类的形象代言人)访问。

2.      类外部:可以通过类的形象代言人访问

(2) Protected成员:

1.       在类内部:直接使用+形象代言人访问。

2.       在类外部:无法访问。可以通过public接口间接访问。

(3) Private成员:

1.   在类内部:直接使用+形象代言人访问。

2.   在类外部:无法访问。可以通过public接口间接访问。

(4) 友元(非类成员): 友元函数是全局的,所以没有public等之分。且友元函数必须要有一个该类的类型参数(名字查找有关)。

     这样就可以在友元函数中通过类的形象代言人访问protected/private成员。

友元类同样无public/protected/private之分。看一个例子:

#include<iostream>

using namespace std;

 

class A{

friend class B;

public:

A():a(10),b(10),c(10){}

A(int i):a(i),b(i),c(i){}

private:

int a;

int b;

int c;

};

 

class B{

public:

int getMya(){return a.a; }

int getMyb(){return a.b; }

int getMyc(){return a.c; }

          

int getOuta(A& oa){return oa.a;}

int getOutb(A& oa){return oa.b;}

int getOutc(A& oa){return oa.c;}

private:

A a;

};

 

 

int main()

{

A oa(100);

B ba;

cout<<ba.getMya()<<endl;

cout<<ba.getMyb()<<endl;

cout<<ba.getMyc()<<endl;

          

cout<<ba.getOuta(oa)<<endl;

cout<<ba.getOutb(oa)<<endl;

cout<<ba.getOutc(oa)<<endl;

}

输出:

10

10

10

100

100

100

BA的友元,那么B中可以通过A的形象代言人访问A的私有成员。

特别提醒:对于形象代言人来说,只有本类内部才算类内部,即使派生类内部也算是基类形象代言人的类外部。

 

Public继承:是一种用的最多的继承方式。

被继承的基类成员访问权限如下:(public,protected,private特性不变)

(1) public成员:在派生类中具有父类同等的访问权限,与派生类本身的public无异。

(2) protected成员:在派生类中继承了该部分成员,说明儿子具备了父亲的protected成员所描述某种特质,但是并不代表儿子可以访问父亲的这些特质。他只能访问继承过来的属于自己的特质。所以在派生类中可以直接访问继承过来的已经属于自己的protected,但是无法通过父类的形象代言人访问父类的protected成员。换句话说对于父类的形象代言人来说派生类中是父类的类外部。当然形象代言人可以通过父类的公有接口间接访问受保护成员。

(3) private成员:在派生类中无法访问,可以通过父类的公有接口间接访问(前题是父类实现了这些接口)。

(4) 在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。

<C++ Primer 4th>中写到:(1)用户代码可以访问类的public成员,而不能访问类的private成员。(2)private只能由基类的成员和友元访问。(3)派生类对基类的访问权限和用户代码相同:可以访问基类的public成员但是无法访问private成员。(以上不适用于protected成员)

(5) 有时作为基类的类具有一些成员,它希望允许派生类访问但仍禁止其他用户访问这些成员。这时我们就需要protected成员。

 

提醒:友元关系不可继承。

Protected继承:用的不多,可用于继承部分接口(网友观点)。

被继承的基类成员访问权限如下:(public,protected,private特性改变)

(1) public成员:变成portected成员,派生类内部可以访问,但外部不可访问。父类的形象代言人可访问。

(2) protected成员:不变,内部可以访问,外部不能访问,父类形象代言人不可访问。

(3) private成员:不变,类内部不可访问。

接口部分继承:

class  A{

public:

    void  interfaceA();

    void  interfaceB();

};

 

class B:protected  A{

public:

     void  interfaceA();

};

这样我就B只是拥有接口interfaceA()了.从这个例子我们可以看出继承重写override是可以改变成员可见性的。不破坏多态。其实继承部分接口也可以这样(如下)。

class A{

public:

    void  interfaceA();

    void  interfaceB();

}

 

class B:public  A{

protected:

     void  interfaceB();

};

这与上面的效果相同。对于不破坏多态性,我们来看一个有趣的例子。

#include<iostream>

using namespace std;

 

class A{

public:

          virtual void show()

          {

                   cout<<"show."<<endl;

          }

};

 

class B:public A{

private:

          void show()

          {

                   cout<<"show in B."<<endl;

          }

};

 

 

int main()

{

          B *pb = new B();

          A *pa = new A();

          pa->show();                  

          pa = pb;

          pa->show();

         //pb->show();//can’t  call,show  is private.

}

输出:

show.

show  in  B.

不但没有破坏多态,居然通过多态实现了调用子类的私有成员函数

 

新的设计思路:通过上述例子我们发现我们可以实现一个父类,然后它有一堆子类,我们可以通过改变接口的访问属性为protected/private或者实现protected/private继承来实现子类无法访问自己的接口,却可以通过多态来实现父类对子类的统一管理。

 

Private继承:很少使用,和protected继承一样是一种实现继承。

被继承的基类成员访问权限如下:(public,protected,private特性改变)

(1)全都变为private:原基类中的publicprotected在类中可以访问,类外部不可以访问。private不可访问。

(2)父类的形象代言人拥有用户代码权限。

 

总结:类成员的访问权限可以归结为两类,类权限用户代码权限。类权限:在本类内部(仅限于本类内部)的权限。用户代码权限:在类外(包括其派生类内部)通过形象代言人访问的权限。

 

对于public,protected,private成员的继承我们可以用一个比方描述其权限改变情况。(适用于public继承)

基类/父类:父亲

派生类/子类:儿子

方法:武功

接口:用于厮杀的武功

保护成员:修练内力的功夫

私有成员:武林秘籍(放在魔法盒中)

public/protected/private接口:打开魔法盒的咒语

 

 

父亲是一位江湖人人敬仰的侠客,拥有绝世武功。有一些是别人能够能见到的,这些它会用于与人厮杀。有一些则是别人不知道的,或者别人无法看到的,比如<<易筋经>>,父亲只会在夜深人静,无人旁观的情况下才会用来修练内力(当然你是他的儿子,你可以看到,如果他教给(你继承)了你,你就会,当然你也不会让别人看到)。同时父亲还有一本武林秘籍,得此秘籍者得天下。由于这本秘籍异常珍贵,所以父亲将他存在魔法盒中,即使别人拿到了魔法盒,也无法打开它。如果你的父亲是一位很爱炫耀的侠士,那么它会选择在公众场合(public)念出咒语(当然这也无关紧要,因为只有拥有你们家族血统的人念出咒语才管用);当然你父亲也可以不这么做,他会在家里(protected)念出来。这样你们也就知道了。你学会了(继承了)就可以用了。如果你父亲很自私的话,他只会私下一个人的时候才会念出咒语(private),这样你永远也打不开父亲给你的盒子(只能做个念想了)。更有甚者,你父亲压根不制造这样一条咒语,因为如果这个盒子里全是它自己的东西的话,他是不需要咒语的,他用指纹就OK了(而指纹是无法继承的-----不在继承的范畴)。

          这个魔法盒很奇特,它可以自我复制,但是却共用同一条咒语。当你继承了父亲的魔法盒后,如果你没有获得咒语你将无法打开。而且你本人也将拥有一个属于自己的魔法盒,如果你父亲的咒语是protected的,那么你父亲给你的魔法盒会放在其中。当你的子孙想要打开你父亲的魔法盒时,必须先打开你的魔法盒,然后再打开你父亲的魔法盒。也就是你需要提供咒语来启用你父亲的咒语。如果你父亲的咒语是public那么你的盒子和他给你的盒子将是并排放着的。你的子孙可以直接用你父亲的咒语打开你继承自父亲的盒子。打开你的盒子自然是用你提供的咒语

 

小结:结合多态+protected/private我们可以实现由父类统一管理子类,并禁止子类调用任何接口的设计。

 

               |  父类的public成员   |  父类的protected成员  | 父类的private成员 
---------------|------------------|---------------------|-----------------

public继承       | public           | protected           | 访问不到           

-------------- |------------------|---------------------|-----------------

protected继承   | protected        | protected           | 访问不到

---------------|------------------|---------------------|-----------------

private继承      | private          | private             | 访问不到

私有继承当然也有别的作用,但是不是非不得已,我们可以用组合来实现。见下文:

http://blog.csdn.net/liaoyoujinb/article/details/14450063

 

 

 

 

 

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值