public private 和protected 继承

在C++中继承主要有三种关系:public、protected和private。这三种继承关系中public继承是最为常用的一种继承关系,private继承是最少见的继承关系。


1. public
从语义角度上来说,public继承是一种接口继承,根据面向对象中的关系而言就是,派生类可以代替基类完成基类接口所声明的行为,也就是必须符合“Liskov替换原则(LSP)”,此时派生类可以自动转换成为基类的接口,完成接口转换。

从语法角度上来说,public继承会保留基类中成员(包括函数和变量等)的可见性不变,也就是说,基类的public成员为派生类的public成员,基类的protected成员为派生类的protected成员。
   
2. protected
从语义角度上来说,protected继承是一种实现继承,根据面向对象中的关系而言就是,派生类不能代替基类完成基类接口所声明的行为,也就是不符合“Liskov替换原则(LSP)”,此时派生类不能自动转换成为基类的接口,就算通过类型转换(static_cast和dynamic_cast)也会得到一个空指针。
从语法角度上来说,protected继承会将基类中的public可见性的成员修改成为protected可见性,相当于在派生类中引入了protected成员,这样一来在派生类中同样还是可以调用基类的protected和public成员,派生类的派生类就也可以调用被protected继承的基类的protected和public成员。例如:

<span style="background-color: rgb(192, 192, 192);"></span><pre name="code" class="cpp">
<span style="font-size:18px;">class CSample1 {
protected:
    void printProtected() {}
public:
void printPublic() {}
};
class CSample2 : protected CSample1 {};
class CSample3 : public CSample2 {
   void print3() {
      printProtected();
      printPublic();
}
};</span>


 
 

3. private从语义角度上来说,private继承是一种实现继承,根据面向对象中的关系而言就是,派生类不能代替基类完成基类接口所声明的行为,也就是不符合“Liskov替换原则(LSP)”,此时派生类不能自动转换成为基类的接口,就算通过类型转换(static_cast和dynamic_cast)也会得到一个空指针。从语法角度上来说,private继承会将基类中的public和protected可见性的成员修改成为private可见性,这样一来虽然派生类中同样还是可以调用基类的protected和public成员,但是在派生类的派生类就不可以再调用被private继承的基类的成员了。

<span style="font-size:18px;"><span style="color:#333333;">class CSample1 {
protected:
  void printProtected() {}
public:
  void printPublic() {}
};
class CSample2 : private CSample1 {};
class CSample3 : public CSample2 {
  void print3() {
    printProtected(); // </span><span style="color:#009900;">编译错误,不可以调用该函数</span><span style="color:#333333;">
    printPublic();    // </span><span style="color:#009900;">编译错误,不可以调用该函数</span><span style="color:#333333;">
  }
};</span></span>

 

4. using声明

如果进行privateprotected继承,则基类成员的访问级别在派生类中比在基类中更受限:

<span style="font-size:18px;">class Base{
public:
    std::size_t size() const {return n;}
protected:
    std::size_t n;
}
 
class Derived : private Base{...};</span>

在这一继承层次中,sizeBase中为public,但在Derived中为private。为了使sizeDerived中成为public,可以在Derivedpublic部分增加一个using声明。如下这样改变Derived的定义,可以使size成员能够被用户访问,并使n能够被从Derived派生的类访问:

<span style="font-size:18px;">class Derived : private Base{
public:
    using Base::size;
privated:
    using Base::n;
    //...
}</span>

 

structclass保留字定义的类具有不同的默认访问级别。同样,默认继承访问级别根据使用哪个保留字定义派生类也不相同。使用class保留字定义的派生类默认具有private继承,而用struct保留字定义的类默认具有public继承:

<span style="font-size:18px;">class Derived : private Base{
public:
    using Base::size;
privated:
    using Base::n;
    //...
}</span>

有一种常见的误解认为用struct保留字定义的类与用class定义的类有更大的区别。实际上它们唯一的不同只是默认的成员保护级别和默认的派生保护级别,除此之外,再也没有其他的区别

 

参考资料:

http://www.cppblog.com/chemz/archive/2007/05/31/25189.aspx

c++primer 4thp482-485

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值