C语言拾遗:公有、私有和受保护的继承--《C++ primer》笔记

本文深入探讨了 C++ 中的公有、私有及保护继承的特点与应用场景,解析了不同继承方式如何影响派生类对基类成员的访问权限,并通过示例代码展示了具体的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 公有继承:派生类对象可访问基类中的公有成员,派生类成员可访问基类中的公有成员与保护成员。
  • 私有继承:对于派生类对象不可该问基类任何成员。派生类成员可该问基类公有与保护成员。所有基类公有与保护成员变成派生类私有成员,且不可为派生类的子类访问。基类私有成员对派生类不可见。
  • 保护继承:派生类对象可访问基类中的公有成员,派生类成员可访问基类公有与保护成员。。基类的公有与保护成员变成派生类的保护成员,且不可为派生类的子类访问。基类私有成员对派生类不可见。

类继承默认私有继承。结构体继承默认公有继承。


以下转自:http://blog.csdn.net/huqinwei987/article/details/7525071


protectedInheritance.cpp

间接继承和书本描述不一致,书上说因为第一重继承变private,第二重继承才无法访问Base::i~是private,现实是提示Base::i是protected,好像跳过Private_derived类直接找基类了。

继承对基类的保护,还是普遍规律,只能越来越严,不能变松。

还有,标号不是限制派生类对基类成员(表达不清楚,是基类成员还是从基类继承过来的成员?)的访问,

原话:所有继承Base的类对Base中的成员具有相同的访问(指什么,成员?怎么理解恰当,派生类包括基类,所以这里的对基类访问指对派生类中包含的基类部分访问?)

标号是限制用户派生类的派生类(也当作一种用户吧?)对派生类(从基类继承来的)成员的访问

[cpp]  view plain copy
  1. //公用、私有和受保护的继承  
  2. #include<iostream>  
  3. class Base{  
  4. public:  
  5.     void basemem();  
  6. protected:  
  7.     int i;  
  8. };  
  9. //struct直接继承class?可以?还有默认访问级别不同,一个public,一个private,转换后不要忘了  
  10. struct Public_derived : public Base{  
  11.     int use_base() { return i; }//顾名思义,使用一下base看看  
  12. };  
  13. struct Protected_derived : protected Base{  
  14.     int use_base() { return i; }  
  15. };  
  16. struct Private_derived : private Base{  
  17.     int use_base() { return i; }//也没问题,尽管private~~~private不是设给它的,是给用户和下一个派生类的  
  18. };  
  19. //下一层派生  
  20. struct Derived_from_Private : public Private_derived{  
  21.     int use_base() { return i; }  
  22.     //书上的注释,Base::i is private in Private_derived,  
  23.     //实际错误提示:'int Base::i' is protected,可能说明直接以用户身份去Base里找了,是protected,如果间接找,这个提示费劲  
  24. };  
  25. struct Derived_from_Public : public Public_derived{  
  26.     int use_base() { return i; }//可以访问,因为Base::i在Public_derived类中仍然是protected  
  27. };  
  28. int main(){  
  29.     Base b;  
  30.     Public_derived d1;  
  31.     Protected_derived d3;  
  32.     Private_derived d2;  
  33.     b.basemem();//b对象,肯定能访问  
  34.     d1.basemem();//对于d1对象,basemem()还是public  
  35.     //d2.basemem();//basemem()是private,不能访问  
  36.     //d3.basemem();//protected当然也不行了  
  37.       
  38. }  

接口继承与实现继承:

public派生的类与基类有相同的接口。在设计良好的层次中,public派生的类可以用在任何需要基类对象的地方。

非public派生的类不继承基类的接口,称为实现继承,(用基类做它的实现,但不用基类做接口)


using.cpp

经过测试,using的用法和书上差距很大~!!!!!!!!!!!!!!!!!!(mark

base的protected,用private继承,结果过用using可以变成public~~~!!!!

另:基类和派生类指针兼容与转换问题也测了一下,结果比较符合我“想当然”的判断。。

到底派生类的constructor怎么定义,把基类的成员用using声明了一遍,但是constructor的初始化列表会提示找不到成员n

[cpp]  view plain copy
  1. //派生类使用using声明恢复继承成员的访问级别。  
  2. #include<iostream>  
  3. class Base{  
  4. public:  
  5.     std::size_t size() const { return n; }  
  6. protected:  
  7.     std::size_t n;  
  8. };  
  9.   
  10. class Derived : private Base{//private继承,全部成员变成私有  
  11. public:  
  12.     using Base::size;  
  13.     //using Base::n;//神奇了,可以提升为public,直接d1.n就访问了。神奇的不是Geany编译器和g++吧  
  14. protected:  
  15.     //using Base::n;  
  16. private://声明成private也行啊。。。到底何谓“不能使访问级别比基类中原来指定的更严格或更宽松”  
  17.     using Base::n;//无论声明放在protected还是private后边,d1.n都提示n是protected。但public...  
  18.     //~小失误,把基类的n设为private,这种情况到底有何不同~恢复为private也有错啊?  
  19. };  
  20. class Public_derived : public Base{//private继承,全部成员变成私有  
  21. public:  
  22.     //using Base::size;  
  23. protected:  
  24.     //using Base::n;  
  25. private:  
  26.     //using Base::n;  
  27. };  
  28.   
  29. int main(){  
  30.     /*Base b1; 
  31.     Derived d1; 
  32.     Public_derived pd1; 
  33.     //猜测:一个对象的存储区域是顺序存放各类对象的,首地址是基类子对象,其次是派生类多出来的部分,再次是派生类的派生类。。。 
  34.     Base *bp1 = &d1;//private继承已经改变了基类的访问权限,所以基类指针也不能指向它了~“Base是Derived里不能访问的一部分”,因此public继承是一个前提。 
  35.     bp1 = &pd1; 
  36.     Public_derived *pdp1 = bp1; //前提:public。派生类的指针是不能指向基类的对象的,只能向下兼容 
  37.     Derived *dp1 = &b1;         //不能向上兼容,所以和地址猜想不冲突,这说明很可能就是哪样排列的,所以不能分。 
  38.     */  
  39.     Derived d1;  
  40.     std::cout << d1.n;//这提升权限到public,但是无法初始化,我始终都搞不定派生类的初始化。。。  
  41. }  


默认继承保护级别(前边疑问的class和struct有解了):

default inheritance.cpp

比较简单的概念,默认不重要,自己可以手动设置


[cpp]  view plain copy
  1. //默认继承保护级别  
  2. class Base{};  
  3. struct D1 : Base{};     //public inheritance by default  
  4. class D2 : Base{};      //private inheritance by default  
  5. //这只是默认的,如果你每次都指定,还是无所谓。。。  
  6. //原书:class和struct唯一的不同是默认的成员保护级别和默认的派生保护级别(这俩词指什么)  
  7.   
  8.   
  9. //以下D3和D4的定义两两相同  
  10. class D3 : public Base{  
  11. public:  
  12.     /*...*/  
  13. };  
  14. //equivalent definition of D3  
  15. struct D3 : Base {      //inheritance public by default  
  16.     /*...*/             //initial number access public by default  
  17. };  
  18.   
  19. struct D4 : Base {  
  20. private:  
  21.     /*...*/  
  22. };  
  23. //equivalent definition of D4  
  24. class D4 : Base {   //inheritance private by default  
  25.     /*...*/             //initial member access private by default  
  26. };  
  27. //tips:因为私有继承在使用class保留字是默认情况,但因为实践中使用罕见,所以还要显式的使用private  
  28. int main(){  
  29.       
  30.       
  31. }  

为何可以访问,却不可以利用构造函数初始化基类成员,派生类中的基类成员,莫非也用基类的构造函数来完成

[cpp]  view plain copy
  1. class Gif : public Picture_format{  
  2. public:  
  3.     Gif(size_t i = 20) : pixels(i) {}  
  4.     size_t fcn(){ return pixels; }  
  5.       
  6. };  
pe15_11.cpp

弄明白的东西:

继承来的成员的地位:

派生类的constructor无法在初始化列表中初始化继承成员,识别不到

对派生类对象来说,继承的成员也是基类的constructor初始化的,但是派生类能直接读取它,fcn()中使用pixels

如此说来,基类派生类貌似真是分开的模块

[cpp]  view plain copy
  1. class Picture_format{  
  2. public:  
  3.     Picture_format(size_t i = 10) : pixels(i) {}  
  4. protected:  
  5.     size_t pixels;//像素  
  6. private:  
  7.       
  8. };  
  9. class Gif : public Picture_format{  
  10. public:  
  11.     size_t fcn(){ return pixels; }  
  12. };  
  13.   
  14.     //Gif g();//这个g不算类Gif的类对象,算个函数什么的吧?!  
  15.     Gif g;  
  16.     std::cout << g.fcn() << std::endl;  
  17.       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值