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. Unity3D 绘制扇形/环形

    using UnityEngine; using System.Collections; using System.Collections.Generic; public class Cone : M ...

  2. BZOJ3203 保护出题人(defend)

    保护出题人(defend) 题目描述 输入 第一行两个空格隔开的正整数n和d,分别表示关数和相邻僵尸间的距离. 接下来n行每行两个空格隔开的正整数,第i + 1行为 a i和 x i,分别表示相比上一 ...

  3. bzoj4292 PA2015 Równanie 枚举

    貌似应该是找出n后,带回去看看是不是对的. #include<cstdio> #include<cstring> #include<algorithm> #incl ...

  4. node.js express配置允许跨域

    app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*& ...

  5. .NET获取URL的各种方式及其区别

    原文发布时间为:2009-11-11 -- 来源于本人的百度文章 [由搬家工具导入] http://www.test.com/testweb/default.aspx?id=1 Request.App ...

  6. MongoDB如何使用“”用户名和密码“”

    在去年的 DB 勒索事件之后, 不少的同学开始加强 Mongodb 的安全性, 其中一种办法就是设置复杂的密码. 那么问题来了, 如果设置的密码里包含一些如 “@”, “:” 一样的特殊字符怎么办? ...

  7. /* Dr黄的技术博客开通啦 */

    以前懒得写技术日志, 现在终于发现重要性.. mark一下这个里程碑.

  8. Nowcoder Girl 参考题解【待写】

    [官方题解]:https://www.nowcoder.com/discuss/65411?toCommentId=1134823 [题目链接]:https://www.nowcoder.com/te ...

  9. 用python登录WeChat(微信) 实现自动回复(非常详细)

    如要转载 麻烦备注好原文出处!!! 最近实现了一些微信的简单玩法 我们可以通过网页版的微信微信网页版,扫码登录后去抓包爬取信息,还可以post去发送信息. >>安装itchat这个库    ...

  10. webpack学习(一)安装和命令行、一次js/css的打包体验及不同版本错误

    一.前言 找了一个视频教程开始学习webpack,跟着视频学习,在自己的实际操作中发现,出现了很多问题.基本上都是因为版本的原因而导致,自己看的视频是基于webpack 1.x版,而自己现在早已是we ...