effective C++ 读书笔记 条款12与条款13
条款12:确定你的public继承塑膜出is-a关系:
这个条款主要将了一些特殊情况:比如企鹅是鸟,企鹅可以继承于鸟,但是鸟会飞,企鹅却不能飞;还有让正方形继承矩形可能也会造成这种尴尬!
这个问题以前想过,但是不知道怎么解决,如果现实生活当中确实要这么使用:比如 猫 狗 鱼 猪等等许多动物继承Animal类,但是猫狗等不会游泳,
假如这里是有很多动物,不能采用鱼里面专门加一个方法! 这个现在还没想出来,条款12也没有讲如果要这么用该怎么处理就是将要避免这样。
is - a;
在面向对象程序设计里面,ia - a指的是类的父子继承关系;
public继承就意味着 is - a ,适用于base - class 身上的每一件事情也一定适应于derived class身上。因此每一个子类对象也是一个父类对象。
条款13:避免遮掩继承而来的名称:
这个条款主要讲了遮掩继承,其实也就是我们经常说的 重载 重写(覆盖) 隐藏;下面就看一下 重载 重写 隐藏的区别:
1、重载的特征:在同一个类中;函数名字相同;参数不同;virtual 关键字可有可无。
2、重写(覆盖)特征是:分别位于派生类与基类;函数名字相同;参数相同;基类函数必须有virtual 关键字(这点非常要注意)。
关于隐藏:
1、如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
2、 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与重写混淆)。
// 06.cpp : 定义控制台应用程序的入口点。 // /************************************************************************/ /* 目的:找出重载、重写、隐藏的区别 时间:2014年12月1日 19:06:03 */ /************************************************************************/ #include "stdafx.h" #include <iostream> using namespace std; class Base { private: int x; public: virtual void mf1() = 0; virtual void mf1(int) //重载,在同一个类当中或者说同一个工作区间内。 { cout<<"调用基类的mf1函数"<<endl; } virtual void mf2() { cout<<"调用基类的mf2函数"<<endl; } void mf3() { cout<<"调用基类的mf3函数"<<endl; } void mf3(double) { cout<<"调用基类的mf3重载函数"<<endl; } }; class Derived:public Base { public: virtual void mf1() { cout<<"调用子类的mf1函数"<<endl; } void mf3() { cout<<"调用子类的mf3函数"<<endl; } void mf4() { cout<<"调用子类的mf4函数"<<endl; } }; int _tmain(int argc, _TCHAR* argv[]) { Derived d; int x; d.mf1();//调用子类的mf1函数 这就是重写(覆盖)这是动态多态的最根本原因 //d.mf1(x);//error C2660: “Derived::mf1”: 函数不接受 1 个参数; //虽然基类Base当中有mf1(int)函数,但是因为子类当中自己也有mf1()函数 //所以发生了隐藏 d.mf2();//这个没有任何问题,子类继承父类的函数,子类当中没有自己的mf2()函数,于是调用父类的函数 d.mf3();//调用子类的mf3()函数;这里基类当中的mf3()函数并没有virtual,但是调用的是子类的函数,说明子类的函数隐藏了父类的函数 // 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与重写混淆)。 //d.mf3(x);//error C2660: “Derived::mf3”: 函数不接受 1 个参数 //虽然基类当中有 mf3(double)函数,但是因为子类当中也有自己的mf3()函数 //所以发生了隐藏 /* 从d.mf1(x)和d.mf3(x)可以看出 virtual void mf1(int)与 void mf3(double),一个有virtual一个没有virtual 但是它们都发生了隐藏。 */ getchar(); return 0; }
上面的代码应该很好的解释了三者的区别;在条款33里面说道如果不想子类隐藏父类的函数,那么在子类当中用using 声明式达到目标:
class Derived:public Base { public: virtual void mf1() { cout<<"调用子类的mf1函数"<<endl; } using Base::mf1; void mf3() { cout<<"调用子类的mf3函数"<<endl; } void mf4() { cout<<"调用子类的mf4函数"<<endl; } };
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。