(一)

以下这段代码:

int x;
void someFunc()
{double x;    //local variablestd::cin>>x; //read a new value to local x
}

这个指涉的是local变量x。而不是global变量x。由于内存作用域会的名称遮掩外围作用域的名称。

当编译器处于someFunc的作用域内并遭遇名称x时,他在local作用域内查找是否有什么东西带着这个名称。假设找到就不再找其它作用域。someFunc的x是double类型而global的x是int类型,并不要紧。C++的名称遮掩规则(name-hiding rules)所做的唯一事情就是:遮掩名称。

至于名称是否是同样或不同的类型,并不重要。

(二)

derived class继承声明于base class内的全部东西。derived class作用域被嵌套在base class作用域内:

class Base {
private: int x;
public: virtual void mf1() = 0; virtual void mf2(); void mf3();
};
class Derived : public Base {
public: virtual void mf1(); void mf4();
};

如果derived class内的mf4的实现像这样:

void Derived::mf4() { mf2();
}

当编译器看到这里使用名称mf2,必须估算它指涉什么东西。查找各作用域。看看有没有某个名为mf2声明式。

首先查找local作用域(也就是mf4覆盖的作用域),没找到不论什么东西名为mf2.于是查找其外围作用域,class Derived覆盖的作用域。还是没找到不论什么东西名为mf2.于是再往外围移动,本例为base class。

在那找到一个名为mf2的东西了。于是停止查找。假设Base还是没有mf2,查找便继续下去。首先找内含Base 的那个namespace的作用域,最后往global作用域找去。

(三)

这次我们重载mf1和mf3,并加入一个新版mf3到derived去:

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

base class内全部名为mf1和mf3的函数都被derived class内的mf1和mf3函数遮掩掉了!

Derived d;
int x;
d.mf1();
d.mf1(x);//错误,Derived::mf1遮掩了Base::mf1
d.mf2();
d.mf3();
d.mf3(x);//错误,Derived::mf3遮掩了Base::mf3

即使base class和derived classes内的函数有不同的參数类型也适用。并且不论函数是virtual或non-virtual也适用。

(四)解决上面的问题的方法!

能够用using声明式达成目标:

class Derived : public Base {
public:
//base class内的public名称在publicly derived class内也应该是public。 using Base::mf1;    // 让base class内为mf1和mf3的全部东西 using Base::mf3;    //在Derived class作用域内都可见(而且public) virtual void mf1(); void mf3(); void mf4();
};Derived d;
int x;
d.mf1();
d.mf1(x);//如今没问题了。调用Base::mf1
d.mf2();
d.mf3();
d.mf3(x);//如今没问题了。调用Base::mf3

这意味着假设你继承base class并加上重载函数,而你又希望又一次定义或覆写(推翻)当中一部分。那么你必须为那些原本会被覆盖的每个名称引入一个using声明式。否则某些你希望继承的名称会被覆盖。

(五)

有时候我们并不希望继承base class的全部函数,这个时候就不能用public方式继承了,由于这违反了"base与derived classes之间的is-a关系!所以这个时候就要用private的继承方式了!

假设Derived唯一想继承的是base class中的那个无參数版本号的mf1。

using在这里派不上用场。using会令继承而来的某给定名称之全部同名函数在Derived class中都可见(在这里假设用using的话,那么在base class中的全部mf1在derived class中都可见!)。

所以在这样的情况下,我们须要一个简单的转交函数(forwarding function):

class Base {
private: int x;
public: virtual void mf1() = 0; virtual void mf1(int); virtual void mf2(); void mf3(); void mf3(double);
};class Derived : private Base {
public: virtual void mf1()//转交函数 { Base::mf1();//暗自转成inline }
};Derived d;
int x;
d.mf1();//调用的是Derived::mf1
d.mf1(x);//错误,Base::mf1()被遮掩了

请记住:

(1) derived class内的名称会遮掩base classes内的名称。在public继承下没有人希望如此。

(2) 为了让遮掩的名称再见天日,可使用using声明式或转交函数(forwarding functions)。

Effective C++:条款33:避免遮掩继承而来的名称相关推荐

  1. 条款33:避免遮掩继承而来的名称

    首先看下下面这个例子: class Base{ private:int x; public:virtual void mf1() = 0;virtual void mf2();void mf3();. ...

  2. Effective C++条款粗略总结

    文章目录 Effective C++ 1.类/结构体 2.资源管理 3.实现 4.模板与泛型编程 5.定制new和delete 6.其他 Effective C++ 1.类/结构体 1.把C++看成一 ...

  3. 【Effection C++】读书笔记 条款32~条款33

    [Effection C++]继承与面向对象设计 条款32:确定你的public继承塑模出is-a关系 "public 继承"意味着"is a".适用于base ...

  4. Effective C++条款(第三版-侯杰译)

    条款一:视C++为一个语言联邦 [C++高效编程守则视情况而变化,取决于你使用的C++哪一部分] 条款二:尽量以const,enum,inline替换#define [对于单纯变量,最好以const对 ...

  5. Effective C++条款39:明智而审慎地使用private继承(Use private inheritance judiciously)

    Effective C++条款39:明智而审慎地使用private继承(Use private inheritance judiciously) 条款39:明智而审慎地使用private继承 1.pr ...

  6. Effective C++条款09:绝不在构造和析构过程中调用virtual函数

    Effective C++条款09:绝不在构造和析构过程中调用virtual函数(Never call virtual functions during construction or destruc ...

  7. Effective C++ 条款34

    条款三十四:区分接口继承和实现继承 这个条款书上内容说的篇幅比较多,但其实思想并不复杂.只要能理解三句话即可,第一句话是:纯虚函数只继承接口:第二句话是:虚函数既继承接口,也提供了一份默认实现:第三句 ...

  8. effective c++条款44 将与参数无关的代码抽离templates

    effective c++条款44 将与参数无关的代码抽离templates 首先了解这个条款的含义:使用template可能导致代码膨胀,二进制码会带着重复(或者几乎重复)的代码.数据,或两者.其结 ...

  9. Effective C++条款40:明智而审慎地使用多重继承(Use multiple inheritance judiciously)

    Effective C++条款40:明智而审慎地使用多重继承(Use multiple inheritance judiciously) 条款40:明智而审慎地使用多重继承 1.多重继承的两个阵营 2 ...

最新文章

  1. react生命周期和组件生命周期
  2. python写端口扫描器_使用Python编写简单的端口扫描器的实例分享
  3. 全链路监控方案概述与比较
  4. ant接口自动化 junit_Jenkins + Ant自动运行Junit测试
  5. 查看博客模板的css代码
  6. Spring BeanDefinition加载
  7. asp版新闻发布今日弄好
  8. 苹果发布紧急公告:老设备11月3日前再不更新就要停止服务啦
  9. 做python开发要用多大的内存卡_编程用surface怎么样发(学python要多大内存)
  10. 设计模式04_抽象工厂
  11. 设计模式学习笔记(九)——Composite组合模式
  12. 推荐一个准确率99.9%的离线IP地址定位服务!
  13. FEC介绍(二)-详解RS编码
  14. 《大型网站技术架构:核心原理与案例分析》.pdf——架构系列必看20本技术书籍
  15. 使用.NET Core和Vue搭建WebSocket聊天室
  16. unity|火焰和烟效果(粒子系统)
  17. 从“站在巨人的肩上”到“跪到侏儒之脚下”——图灵公司副主编自供(二)...
  18. ZT “樱花小萝莉”走红网络 网友:好想生个女儿
  19. 学习Linux的几点忠告(转贴)
  20. 解读图书管理系统为书店带来的好处

热门文章

  1. 从电视到网络,vivo营销之变
  2. Chrome Extension 检查视图(无效)处理方法
  3. KVM虚拟机迁移到VMWare
  4. php trace 函数,PHP Trace 实现原理
  5. word录入表单数据 java 导入系统,java导入excel | 怎么把excel中的数据批量导入到word中的表格中...
  6. 优化自定义函数_10分钟教你手写8个常用的自定义hooks
  7. 必须安利的KubernetesDevOps工具
  8. linux cp无法创建一般文件夹,cp: 无法创建普通文件 : 文件已存在
  9. CF375D Tree and Queries(dsu on tree)
  10. 二分图专题系列各大知识点总结(匈牙利,染色法,最大独立集,最小点覆盖,最小路径覆盖)