Effective C++ 35,36,37
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的更多相关文章
- EC读书笔记系列之16:条款35、36、37、38、39、40
条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...
- Redis 安装,配置,简介,数据类型(一)
Redis 安装 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你 ...
- python工具--获取盛科交换机端口模块类型,波长,传输距离等信息
交换机端口模块信息对应的OID节点为各厂商私有节点,获取其他厂商信息需要把OID进行替换 1 #! /usr/bin/env python 2 #-*-coding:utf-8-*- 3 import ...
- ethereum/EIPs-155 Simple replay attack protection 35,36
EIP 155:重放攻击保护——防止了在一个以太坊链上的交易被重复广播到另外一条链. 在看椭圆曲线时有提到,与r.s.v中的v相关 不同的共有链定义不同的chainId, 防止同一笔交易在不同的共有链 ...
- 【Warrior刷题笔记】剑指offer 6 24 35. 三道题,让你学会链表递归迭代辅助栈
题目一 从尾到头打印链表 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-l ...
- Effective C++ 之 Item 2:尽量以 const, enum, inline 替换 #define
Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 2. 尽量以 const, enum, inline 替换 #d ...
- .NET程序员不加班——写在《华为工程师猝死,36岁,22月无休》之后
我首先承认,有点标题党.因为这是我这个十年老码农——过了年就整整11年了,o(╥﹏╥)o——的个人观察.经验所得.如果有仍在加班的.NET童鞋,不要打我.一定要打的话,只有一个要求:不要打脸! 写这篇 ...
- [转]9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路
1,简介 毕业答辩搞定,总算可以闲一段时间,把这段求职经历写出来,也作为之前三个半月的求职的回顾. 首先说说我拿到的offer情况: 微软,3面->终面,搞定 百度,3面->终面,口头of ...
- 9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路
1,简介 毕业答辩搞定,总算可以闲一段时间,把这段求职经历写出来,也作为之前三个半月的求职的回顾. 首先说说我拿到的offer情况: 微软,3面->终面,搞定 百度,3面->终面,口头of ...
随机推荐
- [MUTC2013][bzoj3513] idiots [FFT]
题面 传送门 思路 首先有一个容斥原理的结论:可以组成三角形的三元组数量=所有三元组-不能组成三角形的三元组 也就是说我们只要求出所有不能组成三角形的三元组即可 我们考虑三元组(a,b,c),a< ...
- 求和为s的连续正数序列
输入一个正数是s,打印出所有和为s的连续正数序列(至少含有两个数).例如输入15,由于1+2+3+4+5=4+5+6==7+8=15,所有结果打印出3个序列1-5,4-6,7-8. 代码如下: voi ...
- [USACO Section 5.3]量取牛奶 Milk Measuring (动态规划,背包$dp$)
题目链接 Solution 完全背包 \(dp\) , 同时再加一个数组 \(v[i][j]\) 记录当总和为\(j\) 时第 \(i\) 种物品是否被选. 为保证从小到大和字典序,先将瓶子按大小排序 ...
- MFC 禁用输入法
#include <Imm.h> HIMC m_hImc; // 全局或者成员变量 // Function for Disabling IME void CMyDialog::Disabl ...
- Linux下实现mysql数据库每天自动备份
Linux下实现mysql数据库每天自动备份 1.基本操作步骤 a.创建备份目录 mkdir -m 777 /home/wwwroot/backup b.创建备份脚本sh vim /home/wwwr ...
- codechef AUG17 T4 Palindromic Game
Palindromic Game Problem Code: PALINGAM There are two players A, B playing a game. Player A has a st ...
- div模拟dropdownlist控件 div下拉菜单
原文发布时间为:2009-10-16 -- 来源于本人的百度文章 [由搬家工具导入] 控件发布:div2dropdownlist(div模拟dropdownlist控件) div3dropdownli ...
- MEF 注入[转载]
领域服务的时候,用到MEF的注入有参构造函数的方法,your master was attracted,打算稍微深挖一下,这篇来对此知识点做个总结. 一.知识点回顾 MEF作为IOC的方式之一,它的主 ...
- C++ primer分章节快速回顾
第三章: 1,sozeof(int): int n_int=INT_MAX; sizeof n_int;(对变量括号可选) 2,#include<climits>包含一些类型的最大值3,c ...
- linux定时问题
手动运行java脚本,可以,但定时运行没效果 查看脚本是否赋予执行权限:若无则赋予可执行权限,若还是没用,则在脚本增添环境变量,百度搜索.