最近重新捧起了《Effective c++》,其中味道又有不同,这里记录之。。。

  这篇文章记录一下public继承的知识点...

(1)public继承的意义
  该继承方式是代表is-a(是一种)的关系,即施加于基类的所有操作,同样能施加于派生类;换句换说,比如存在类A(person)和类B(student),且类B以public的方式继承于类A,那么可以说类B对象也是类A对象的一种,那么能施加于类A(person)的操作(比如eat),必然能施加于类B上;如果不满足这种关系,就不能用public继承,而需要考虑其他设计,来约束这两个类之间的关系。以上就是public继承的意义之所在,明白这个意义能够指导,能否直接将一个object以public的方式继承于另一个object!!!
(2)public继承的实质
  在设计继承体系时,对于函数属性的设置往往令人头痛,到底是设置为virtual还是non-virtual呢,有时还会因为是否将一个类设为abstract class而耿耿于怀,以上这些问题的出现,表示我们还没有弄明白继承体系中,这些属性设置的真正含义之所在。这里还要记录一下public继承自身的特点,即父类中public属性的成员(成员函数和成员变量)被子类继承后,依然是public属性;private属性和protected属性以此类推。
下面就一个例子来说明public继承的实质:

 class A{
public:
//...(省略构造函数和析构函数)
virtual void pureVirFunc() const = ;
virtual void virFunc() const;
void nonVirFunc() const;
private:
//...(省略成员变量)
};

上述类A定义了三个成员函数,代表三种属性的函数,即纯虚函数,非纯虚函数和非虚函数;这三种函数在继承时有着各自的行为,这些行为代表着继承的实质。

 class B : public A{
public:
//...(省略构造函数和析构函数)
virtual void pureVirFunc() const;
virtual void virFunc() const;
// 对于类A中的nonVirFunc函数,这里
// 不能重写
private:
//...
};

简单阐述三种函数继承时的行为:
1.纯虚函数——类A将pureVirFunc设置为纯虚函数,表明类A是一个abstract class,它不能产生具体的对象,肆意去生成类A的对象的行为是愚蠢的,但能够声明它的指针,用其指针指向具体的派生类对象,达到动态绑定的效果,如此:
----------------------------------------------------
A a; //错误,不能为abstract class生成具体对象
A* pa = new B();//正确
pa->virFunc(); //动态绑定,调用的是类B的函数
----------------------------------------------------
类A将pureVirFunc设置为纯虚函数,以此来告知各位子类(以public的方式继承于类A),对于该函数对应的行为,它只是声明函数接口(子类们也只能继承该接口的声明),具体如何实现那是子类们自己的事情。当然,C++也给予那些多事的abstract class一个方便——能为纯虚函数提供显示的定义;但是,由于子类必须重写纯虚函数(不然,子类也是abstract class),这样看来,abstract基类为纯虚函数提供显示定义似乎没有必要,因为子类根本用不上。的确,除了用来耍酷,一般是用不上的,不过,《Effective c++》中阐述了一种情况,为纯虚函数提供显示定义的行为是有必要。
2.非纯虚函数——较之纯虚函数,一般的虚函数更常用,毕竟大部分对象时具体的,就应该能让它们产生对象;父类赋予某个函数的属性为impure virtual时,一般会附带默认的实现,该情况对应上面例子中的virFunc函数,即告知其子类,该行为对应的函数,它提供了函数接口声明,并附上其默认实现,如果默认实现能完成某个子类的需要的功能,那么该子类直接继承而不需重写该函数;不然,就需要重写该函数,来满足自己的需求。大部分情况下,子类对于父类提供的默认实现都不太满意,会重写继承而来的impure virtual函数,以此来体现继承体系中的多态性。
3.非虚函数——如果父类将某个行为定义为非虚函数,该情况对应上面例子中的nonVirFunc函数,即告知各位子类,它提供了该行为对应的函数接口声明和必要的实现,并且该函数的实现能满足子类的需求(即便以后发生其他变化),它不希望子类们自以为是的去重写这类函数。反过来想,如果父类提供的实现不能满足子类未来的需求,那就应该将该函数声明为虚函数而不是非虚函数了,对吧?

最新文章

  1. android studio 1.0 开发 ndk 调用 c++ so库
  2. 会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载
  3. Oracle索引(B*tree和Bitmap)学习
  4. Eclipse Ctrl+Tab Alt+/ 快捷键
  5. mongodb数据库设计原则
  6. Linux下RPM软件包的安装及卸载
  7. Mysql MyISAM数据库批量转换表引擎为Innodb
  8. Java 中判断char 是否为空格 和空
  9. 从git上下载代码并导入eclipse
  10. IOS引导页的编写
  11. StringEscapeUtils.unescapeHtml的使用
  12. 前端小课堂 js:函数的创建方式及区别
  13. Git多帐号配置,管理多个SSH
  14. LocalMaxima_NOI导刊2009提高(1)
  15. Windows中查看进程的资源消耗(cpu, Disk,Memory,NetWork)
  16. java 学习笔记
  17. php获取服务器信息常用方法(零碎知识记忆)
  18. luogu P3980 [NOI2008]志愿者招募
  19. MySQL复制异常大扫盲:快速溯源与排查错误全解
  20. keepalived nginx 双机热备图文讲解

热门文章

  1. Html学习_style属性应用
  2. POSIX多线程编程(上)-基本概念
  3. 获取PDF页数
  4. Java 代码优化过程的实例介绍
  5. Java OCR tesseract 图像智能字符识别技术 Java实现
  6. 1008: [HNOI2008]越狱
  7. UVALive 3211 Now or later
  8. YCbCr
  9. Android 多屏幕适配
  10. Linux学习之CentOS6下Mysql数据库的安装与配置