35.使公有继承体现 “是一个” 的含义。

共同拥有继承意味着 “是一个”。如  class B:public A。 说明类型B的每个对象都是一个类型A的对象,A比B具有更广泛的概念。而B表示一个更特定的概念。

在C++中不论什么一个參数为基类的函数都能够实际取一个派生类的对象,仅仅有共同拥有继承会如此。对于共同拥有继承,如AB。若有两个函数 一个函数为 void fun1(A &a);还有一个函数为void fun2(B& b);则对于AB的两个对象a。和b。对于 fun1(a)和fun2(b和fun1(b))都是正确的。fun2(a)是错误的。注意仅仅有共同拥有继承才有这个特性,对于私有继承会与此不同。并且这是说 B的对象 "是一个“ A的对象,可是B的数组并非一个A的数组。

使用公有继承常常遇到的问题是对基类适用的规则并不适用于派生类。但公有继承又要求对基类对象适用的不论什么东西都适用于派生类对象,使用公有继承会导致一些错误的设计。

如对于企鹅与鸟,鸟是基类,其有嘴,翅膀等数据成员。另一个飞的成员函数virtual void fly();一開始你觉得鸟有一些属性。且鸟会飞,然后你有觉得企鹅公有继承于鸟,即企鹅是一种鸟,可是问题出现了,企鹅不会飞。

让企鹅直接公有继承于鸟类。这是一个错误的设计。所以你想去改进它,在依旧使用公有继承的前提下。

1.世上有非常多鸟不会飞,于是你将鸟类分成了两种,FlyingBird 和NoFlyingBird,分成会飞和不会飞两种鸟类,这两种鸟类都公有继承于鸟类,而企鹅公有继承于NoFlyingBird。

2.企鹅中依旧有fly()这个函数,可是又一次定义了这个fly函数。使之产生一个执行时错误,使企鹅是鸟,企鹅能飞,可是让企鹅飞的这个操作是错误的。

这是一个执行时才干检測的错误。

当利用一些知识和常识设计一些类并使用公有继承时,可是公有继承却没那么有效,由于最关键的问题是基类中的规则要相同适用于派生类对象,而我们想要用继承实现的对象却有两者不同的规则。而对于这种情况,一般要用”有一个“ 和”用。。

。来实现“这两种关系来实现。

36.区分接口继承和实现继承。

首先,接口是放在public中给外部调用的。而实现是隐藏在private中的内部逻辑。对于类的继承,有时希望派生类仅仅继承成员函数的接口。有时派生类同一时候继承函数的接口和实现。且同意派生类改写实现,有时派生类同一时候继承类的接口与实现。可是不同意改动不论什么东西。

纯虚函数必需要在详细实现类中又一次声明,它们在抽象类中往往未定义。定义纯虚函数的目的在于使派生类只 继承函数的接口。也就是第一种情况,这样的情况非常easy理解。

可是纯虚函数事实上是能够提供定义的。

对于另外一种和第三种情况,继承函数的接口和实现,一般使用虚函数来实现。

而须要改进的地方是。对于一个基类中的虚函数,其有一定的实现。而派生类能够继承这种接口和实现,既能够直接继承基类中这个接口,也能够重写这个接口的实现。

这样非常科学,可是又要一个问题,当一个新的派生类继承这个基类时。因为这个类中使用虚函数做接口,导致新的程序猿忘记了又一次声明这个虚函数并给予新的实现逻辑而去错误的使用虚函数中的默认逻辑而造成了错误。为了提供更安全的基类,使用纯虚函数做接口,让纯虚函数有自己缺省实现,在派生类继承时。直接调用基类纯虚函数的实现:

class A{
public:
virtual void fun() const = 0;
};
void A::fun() const{
cout<<"Class A"<<endl;
}
class B:public A{
public:
virtual void fun() const; };
void B::fun() const{
A::fun();
}

如上所看到的,使用一个纯虚函数。可是带有缺省实现,而派生类继承时就必须又一次声明这个纯虚函数,而对于要调用基类的缺省实现时,除了上面直接调用基类的这个纯虚函数外,还能够通过在基类中的protected中设置一个默认的实现函数,如 void defaultFun() const。而派生类会继承这个默认实现,然后在派生类的又一次定义的虚函数中调用这个默认的实现函数就可以。

这个情况事实上就是另外一种情况,继承函数的接口和实现,且可以改动实现。一般使用虚函数。可是使用带默认操作的纯虚函数会更加安全。安全是一个非常重要的问题,假设不考虑安全性,非常多在Effective C++这本书中讨论的问题都是没有意义的,由于假设你明确之前程序的设定。就知道哪些事情该做,哪些事情不该做,就不会去犯一些错误,可是对于一个程序的开发。不是有一个人完毕的。当你理解自己的设定时,别人却不知道,维护你代码的人任意的做一些他们觉得应该可以做到的安全的事,却由于你之前考虑的不周全而使这些行为极度不安全。所以要认真考虑安全性的问题。写出尽可能完美安全的代码。

对于第三种情况,声明非虚函数。目的在于使派生类继承函数的接口和强制性实现,又因为不应该在派生类中又一次声明和定义基类的非虚函数,所以不会改动非虚函数的实现的。

所以,要理解纯虚函数,简单虚函数和非虚函数声明和功能上的差别。不用操心虚函数的效率问题,由于这真的是小问题,全部基类都应该虚函数。

一些函数不应该在派生类中又一次定义就要将其定义为非虚函数。

37.决不要又一次定义继承而来的非虚函数。

首先,对于又一次定义继承的非虚函数,称为对这个函数的隐藏。这是一种不经常使用的东西,正是由于有这个设定,绝不又一次定义继承而来的非虚函数。

这样做的原因也是非常easy理解的,也是多态的长处:

class A{
public:
void fun() const{
cout<<"Class A"<<endl;
}
};
class B:public A{
public:
void fun() const{
cout<<"Class B"<<endl;
}
};
int main(){
B* b = new B();
A* a = b;
b->fun();
a->fun();

对于以上代码,对同一个对象,也就是b指向的对象,当将其转换为基类指针后,因为其为静态绑定的,其所指向的函数不同,获得了不同的结果。而多态时动态绑定,指向的函数通过虚指针指向同样的地址。

结论是,对于类B的对象,其又一次定义的函数fun()被调用时。其行为是不确定的,而决定因素与对象本身没有关系,而取决于指向它的指针的声明类型,引用也会和指针表现出这种异常行为,这种行为是不合理的。

而从理论上来考虑。对于公有继承意味着 ”是一个“,对于B中又一次定义了A中的实现后,B就不”是一个“ A了。

Effective C++ 35,36,37的更多相关文章

  1. EC读书笔记系列之16:条款35、36、37、38、39、40

    条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...

  2. Redis 安装,配置,简介,数据类型(一)

      Redis 安装 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你 ...

  3. python工具--获取盛科交换机端口模块类型,波长,传输距离等信息

    交换机端口模块信息对应的OID节点为各厂商私有节点,获取其他厂商信息需要把OID进行替换 1 #! /usr/bin/env python 2 #-*-coding:utf-8-*- 3 import ...

  4. ethereum/EIPs-155 Simple replay attack protection 35,36

    EIP 155:重放攻击保护——防止了在一个以太坊链上的交易被重复广播到另外一条链. 在看椭圆曲线时有提到,与r.s.v中的v相关 不同的共有链定义不同的chainId, 防止同一笔交易在不同的共有链 ...

  5. 【Warrior刷题笔记】剑指offer 6 24 35. 三道题,让你学会链表递归迭代辅助栈

    题目一 从尾到头打印链表 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-l ...

  6. Effective C++ 之 Item 2:尽量以 const, enum, inline 替换 #define

    Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 2. 尽量以 const, enum, inline 替换 #d ...

  7. .NET程序员不加班——写在《华为工程师猝死,36岁,22月无休》之后

    我首先承认,有点标题党.因为这是我这个十年老码农——过了年就整整11年了,o(╥﹏╥)o——的个人观察.经验所得.如果有仍在加班的.NET童鞋,不要打我.一定要打的话,只有一个要求:不要打脸! 写这篇 ...

  8. [转]9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路

    1,简介 毕业答辩搞定,总算可以闲一段时间,把这段求职经历写出来,也作为之前三个半月的求职的回顾. 首先说说我拿到的offer情况: 微软,3面->终面,搞定 百度,3面->终面,口头of ...

  9. 9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路

    1,简介 毕业答辩搞定,总算可以闲一段时间,把这段求职经历写出来,也作为之前三个半月的求职的回顾. 首先说说我拿到的offer情况: 微软,3面->终面,搞定 百度,3面->终面,口头of ...

随机推荐

  1. POJ 3678 Katu Puzzle(2-SAT,合取范式大集合)

    Katu Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9987   Accepted: 3741 Descr ...

  2. 15个变态的Google面试题以及答案

    在当前经济形势不景气的情况下,谷歌招聘新员工是一件令人振奋的事,特别是对那些在当前金融风暴中渴望找到安全港的年轻经理们和软件开发商们来说是个好消息. 不过,也不要高兴太早,谷歌在招聘新员工时,更加青睐 ...

  3. bzoj 2503 相框 分类讨论

    题目大意:给定一张无向图,每次可以进行以下两种操作: 1.将一个点分裂成一些点,原先这个点连接的每条边任选一个新点进行连接 2.将两个度数为1的点合并为1个点 求将这个图变成一个环的最小操作次数 我们 ...

  4. Origin 2018 的坐标轴中文标签发生倒立/翻转

    问题: 在使用 origin 2018 作图时,坐标轴或者是标签中输入中文后,将其更换中文字体(英文字体没有该问题)后发生倒立的情况 解决: 后来发现 Origin 2018 中存在两种中文字体,其中 ...

  5. 一个javascript继承和使用的例子

    继承可以帮助我们实现代码的重用,把对象的属性写入构造函数,对象的方法写入原型后,以下例子演示继承的使用: 示例的css和js在后 父实例,得到一个间隔1s的轮播: <!DOCTYPE html& ...

  6. Mysql EXISTS NOT EXISTS

    SELECT c.CustomerId, CompanyName FROM Customers c WHERE EXISTS( SELECT OrderID FROM Orders o WHERE o ...

  7. 【CF1015D】Walking Between Houses(构造,贪心)

    题意:从1开始走,最多走到n,走k步,总长度为n,不能停留在原地,不能走出1-n,问是否有一组方案,若有则输出 n<=1e9,k<=2e5,s<=1e18 思路:无解的情况分为两种: ...

  8. linux多线程学习笔记六--一次性初始化和线程私有数据【转】

    转自:http://blog.csdn.net/kkxgx/article/details/7513278 版权声明:本文为博主原创文章,未经博主允许不得转载. 一,一次性初始化 以保证线程在调用资源 ...

  9. 修复受损的linux引导

    想来楼主玩linux差不多近20年了,从redhat,mandrke,manjaro,汉化,听歌.看电视电影.上网.打游戏.配置打印机等,碰到的问题一一解决了,但是一直对装好linux后重新安装win ...

  10. js 验证数字的正则表达式集

    <script type="text/javascript">     function validate(){       var reg = new RegExp( ...