首先介绍一个原则LSP(Liskov Substitution Principle),如果Class D以Public方式继承Class B,则所有B对象可以派上用场的任何地方,D对象一样可以派上用场。

对于重载和重写,相信大家都已经有所了解。这里讨论一下在public继承的时候,重载函数的问题。

先看下面的例子:

 class Base
{
public:
virtual void mf1() = ;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
...
private:
int x_;
};
class Derived:public Base
{
public:
virtual void mf1();
void mf3();
void mf4();
...
};

在基类中,mf1() 和mf3()都被重载,子类public继承父类,这里的子类覆盖了父类中所有名为mf1和mf3的函数。因而以下调用有些会失败。

Derived d;
int x;
...
d.mf1(); // Derived::mf1
d.mf1(x); //错误 Derived::mf1 hiden Base::mf1
d.mf2(); // Base::mf2
d.mf3(); // Derived::mf3
d.mf3(x); //错误Derived::mf3 hiden Base::mf3

由此可见,及时子类和父类内的函数有不同的参数时,子类的函数还是会覆盖所有父类中同名的函数。

这样做的原因:避免从疏远的父类中继承重载函数。但是实际上,public继承应该遵循LSP原则,即父类和子类是Is-a 的关系,所以我们可以通过using,显示地实现对父类同名重载函数的继承。

 class Base{...}; //同上
class Derived:public Base{
public:
//让Base class内名为mf1与mf3的所有东西在
//Derived作用域内都可见(并且都是public)
using Base::mf1;
using Base::mf3;
....//同上
};
Derived d;
int x;
...
d.mf1(); //no problem. call Derived::mf1
d.mf1(x); //no problem. Base::mf1
d.mf2(); //no problem. call Base::mf2
d.mf3(); //no problem. call Derived::mf3
d.mf3(x); //no problem. Base::mf3

如果你不想继承所有的重载函数,则你不应该使用public继承,因为这样会违反LSP原则,你可以使用private继承,为了选择性的继承重载函数,可以使用inline 转交函数(forwarding function),具体实现如下:

 class Base
{
public:
virtual void mf1() = ;
virtual void mf1(int);
... //same as above
};
class Derived:private Base
{
public:
virtual void mf1()//转交函数(forwarding function)
{
Base::mf1();
}
...
};
...
Derived d;
int x;
d.mf1(); //good! call Derived::mf1
d.mf1(x); //Error as suppose,Base::mf1() was hidden.

关键:

  子类内的名称会遮掩父类内的名称,在pubilc继承下,不应该这样做。

  为了使被遮掩的名称可见,使用using声明或者转交函数。

Effective C++ 33 避免遮掩继承而来的名称的更多相关文章

  1. [Effective C++ --033]避免遮掩继承而来的名称

    这一章一直在想怎么写,因为比较基础,很容易理解,就按照需要来写吧. 假设我们有这样一个类: class Base { private: int x; public: ; virtual void mf ...

  2. Effective C++ -----条款33:避免遮掩继承而来的名称

    derived classes内的名称会遮掩base classes内的名称.在public继承下从来没有人希望如此. 为了让被遮掩的名称再见天日,可使用using声明式或转交函数(forwardin ...

  3. Effective C++ Item 33 避免遮掩继承过来的名称

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie ? 不懂 c++为什么derived classes 内的名称要遮掩 base classe ...

  4. Effective C++:条款33:避免遮掩继承而来的名称

    (一) 以下这段代码: int x; void someFunc() { double x; //local variable std::cin>>x; //read a new valu ...

  5. 条款33:避免遮掩继承而来的名称(Avoiding hiding inherited names)

    NOTE: 1.derived classes 内的名称会遮掩base classes内的名称.在public继承下从来没有人希望如此. 2.为了让被遮掩的名称再见天日,可使用using 声明方式或转 ...

  6. 读书笔记_Effective_C++_条款三十三:避免遮掩继承而来的名称

    名称的遮掩可以分成变量的遮掩与函数的遮掩两类,本质都是名字的查找方式导致的,当编译器要去查找一个名字时,它一旦找到一个相符的名字,就不会再往下去找了,因此遮掩本质上是优先查找哪个名字的问题. 而查找是 ...

  7. [EffectiveC++]item33:避免遮掩继承而来的名称。

    先看看: ZT C++ 重载.覆盖和隐藏的区别 http://www.cnblogs.com/jeanschen/p/3405987.html 隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下: ...

  8. effective C++ Item 33 避免隐藏继承而来的名字

    1. 普通作用域中的隐藏 名字实际上和继承没有关系.有关系的是作用域.我们都知道像下面的代码: int x; // global variable void someFunc() { double x ...

  9. 读书笔记 effective C++ Item 33 避免隐藏继承而来的名字

    1. 普通作用域中的隐藏 名字实际上和继承没有关系.有关系的是作用域.我们都知道像下面的代码: int x; // global variable void someFunc() { double x ...

随机推荐

  1. HDU 1524 A Chess Game【SG函数】

    题意:一个N个点的拓扑图,有M个棋子,两个人轮流操作,每次操作可以把一个点的棋子移动到它的一个后继点上(每个点可以放多个棋子),直到不能操作,问先手是否赢. 思路:DFS求每个点的SG值,没有后继的点 ...

  2. 第24章 java线程(3)-线程的生命周期

    java线程(3)-线程的生命周期 1.两种生命周期流转图 ** 生命周期:**一个事物冲从出生的那一刻开始到最终死亡中间的过程 在事物的漫长的生命周期过程中,总会经历不同的状态(婴儿状态/青少年状态 ...

  3. PAT 1035. 插入与归并(25)

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...

  4. ReactNative新手学习之路05 使用夜神模拟器调试ReactNative

    1.首先确保adb环境添加到path环境   2.安装好夜神模拟器   3.运行模拟器   4.adb connect 127.0.0.1:62001   5.摇一摇设置IP和端口 如127.168. ...

  5. Ext小总结

    titleCollapse:true,//高级搜索点击隐藏显示 添加按钮 >弹出页面 1.添加按钮 //核销  在控制层页面添加页面路径>添加操作按钮>window.allOrder ...

  6. 深入理解Java:类加载机制及反射

    说明:本文乃学习整理参考而来. 一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构 ...

  7. FineUI小技巧(5)向子窗口传值,向父窗口传值

    前言 FineUI中经常会用到启用IFrame的Window控件,这样有助于从物理上进行代码解耦和.IFrame的引入就会涉及传值问题,如何在父窗口和子窗口之间相互传值呢? 向子窗口传值 向子窗口传值 ...

  8. 我常用的VS技巧

    声明:开发工具使用的是VS2013 1.开发 包括编辑,代码补全等 1.1快速选择一行 第一种方式:鼠标停留在要选择的行上,三击. 第二种方式:鼠标停留在要选择的行上,按home键将鼠标停留在行首,按 ...

  9. ASP.NET中的缓存机制

    ASP.NET 提供一个功能完整的缓存引擎,页面可使用该引擎通过 HTTP 请求存储和检索任意对象.缓存的生存期与应用程序的生存期相同,也就是说,当应用程序重新启动时,将重新创建缓存. 将数据添加到缓 ...

  10. Matlab2015入门学习02

    1. 续行符 ... 当物理的一行之内写不下时, 在 物理行的结尾加上三个小黑点 >>跟在运算符之后,可以不留space空格 >>跟在数字之后,若不留白space,出错; 留一 ...