Effective C++ 33 避免遮掩继承而来的名称
首先介绍一个原则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 避免遮掩继承而来的名称的更多相关文章
- [Effective C++ --033]避免遮掩继承而来的名称
这一章一直在想怎么写,因为比较基础,很容易理解,就按照需要来写吧. 假设我们有这样一个类: class Base { private: int x; public: ; virtual void mf ...
- Effective C++ -----条款33:避免遮掩继承而来的名称
derived classes内的名称会遮掩base classes内的名称.在public继承下从来没有人希望如此. 为了让被遮掩的名称再见天日,可使用using声明式或转交函数(forwardin ...
- Effective C++ Item 33 避免遮掩继承过来的名称
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie ? 不懂 c++为什么derived classes 内的名称要遮掩 base classe ...
- Effective C++:条款33:避免遮掩继承而来的名称
(一) 以下这段代码: int x; void someFunc() { double x; //local variable std::cin>>x; //read a new valu ...
- 条款33:避免遮掩继承而来的名称(Avoiding hiding inherited names)
NOTE: 1.derived classes 内的名称会遮掩base classes内的名称.在public继承下从来没有人希望如此. 2.为了让被遮掩的名称再见天日,可使用using 声明方式或转 ...
- 读书笔记_Effective_C++_条款三十三:避免遮掩继承而来的名称
名称的遮掩可以分成变量的遮掩与函数的遮掩两类,本质都是名字的查找方式导致的,当编译器要去查找一个名字时,它一旦找到一个相符的名字,就不会再往下去找了,因此遮掩本质上是优先查找哪个名字的问题. 而查找是 ...
- [EffectiveC++]item33:避免遮掩继承而来的名称。
先看看: ZT C++ 重载.覆盖和隐藏的区别 http://www.cnblogs.com/jeanschen/p/3405987.html 隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下: ...
- effective C++ Item 33 避免隐藏继承而来的名字
1. 普通作用域中的隐藏 名字实际上和继承没有关系.有关系的是作用域.我们都知道像下面的代码: int x; // global variable void someFunc() { double x ...
- 读书笔记 effective C++ Item 33 避免隐藏继承而来的名字
1. 普通作用域中的隐藏 名字实际上和继承没有关系.有关系的是作用域.我们都知道像下面的代码: int x; // global variable void someFunc() { double x ...
随机推荐
- Hibernate注解配置
在之前的第一次对框架的实际应用中,我使用的是Hibernate的xml配置方法,xml配置方法非常繁琐, 还是推荐所有使用Hibernate的人使用注解方式进行配置,在这篇文章中,我将列举出我们常用的 ...
- Hibernate中Java对象的三种状态
Hibernate中Java对象的三种 ...
- WINDOW的cmd的命令【转载】
转载地址:https://zhidao.baidu.com/question/583956458.htmlwinver---------检查windows版本 wmimgmt.msc----打开win ...
- 简单了解ICMP协议
ping命令是什么协议? 维基百科: ping是一种电脑网络工具,用来测试数据包能否通过IP协议到达特定主机.ping的运作原理是向目标主机传出一个ICMP echo@要求数据包,并等待接受echo回 ...
- 让所有的浏览器都能识别HTML5标签样式的小插件
如今HTML5愈来愈引发大家的关注了,但目前支持HTML5的浏览器还不是主流,特别是国内用户近50%以上仍旧使用IE6,由于支持HTML5的IE9不支持Xp系统安装,这样未来很长一段时间,HTML5的 ...
- 【平面设计AFTER】读到的设计海报分层法
来源参考:http://www.uisdc.com/graphic-designer-self-improvement 分层法的三层:“背景层”,“图形层”,“信息层” 1,背景层,一般为纯色,场景, ...
- Java static 静态代码块执行分析
假设有这样一个类: public class Utils { static { Log.i("static","isLoad!"); } public stat ...
- 【asp.net】Linux 部署 asp.net core 项目
Net sdk官网LINUX配置地址:https://www.microsoft.com/net/core#windows 参考:http://www.07net01.com/2016/08/1638 ...
- hadoop在网页客户端的maven配置
hadoop网页客户端maven配置,只能在tomcat7上运行,tomcat6和tomcat8运行会出错,我用的是tomcat-7.0.67 完整的pom.xml内容为: <!-- 这个配置只 ...
- Log4net中换行符
在log4net节点中 <appender name="DebugLogFileAppender" type="log4net.Appender.FileAppen ...