名字查找与继承
来源:互联网 发布:出题软件手机版 编辑:程序博客网 时间:2024/06/06 09:54
C++函数解析过程
理解上面的名字查找过程,再来理解隐藏(hide)、覆盖(override)、重载(overload)就容易多了。此外还要记得:名字查找先于参数检查。
- overload: 重载 发生在同一个域内,同一个域名字相同但是参数不同的多个函数。
- override:覆盖 发生在多态继承的继承体系中,派生类会override基类的virutal函数。
- hide: 隐藏 发生在不同域之间,深层次的名称会hide外层的名称
一个例子
来看一个例子。
#include <iostream>class Base { public: virtual int fcn() { std::cout << "int Base::fcn()" << std::endl; }};class D1 : public Base{ public: //using Base::fcn; // 可以使用using让被隐藏的Base::fcn重见天日 int fcn(int) // 隐藏了 Base::fcn { std::cout << "int D1::fcn(int)" << std::endl; } virtual void f2() { std::cout << "void D1::f2()" << std::endl; }};class D2 : public D1{ public: int fcn(int) // 隐藏(hide)了D1::fcn { std::cout << "int D2::fcn(int)" << std::endl; } int fcn() // 覆盖(override)了Base::fcn { std::cout << "int D2::fcn()" << std::endl; } void f2() // 覆盖(override)了D1::f2 { std::cout << "void D2::f2()" << std::endl; }};
分析1
Base b; D1 d1; D2 d2; b.fcn(); // Base::fcn d1.fcn(1); // int D1::fcn(int) d1.f2(); // void D1::f2() //d1.fcn(); // compile error : int D1::fcn(int) hide Base::fcn d1.Base::fcn(); // compile error : int D1::fcn(int) hide Base::fcn
其中D1的int fcn(int)
隐藏了(hide)int Base::fcn()
。我一开始有一个错误的观念,以为隐藏就是不要某个函数了,这么理解是错误的。public继承意味着“is-a”的关系(见Effective C++ rule32), 派生类会包含基类的所有东西,隐藏并不是说剔除了某个函数,而是说名字被隐藏了,注意结合上面的名字查找过程来理解。
当编译器看到d1.fcn()
这句时,编译器会先确定d1的静态类型,此时为D1, 然后在D1内找名字fcn, 它找到了一个fcn:int fcn(int)
, 就不会在往基类那里找了, 接着进行参数匹配,此时编译器就会报错,因为参数检查没有通过。
那么如果我们想通过D1调用到Base::fcn怎么办呢? 可以使用using或者给fcn加上Base域或者使用Effective c++ rule34中提到的转交函数。
分析2
Base* bpb, *bpd1, *bpd2; bpb = &b; bpd1 = &d1; bpd2 = &d2; bpb->fcn(); bpd1->fcn(); bpd2->fcn();
结果:
int Base::fcn()int Base::fcn()int D2::fcn()
此例是让基类指针分别指向三种对象,bpd1指向D1类的对象,解析过程是这样的:
- bpd1的静态类型,为Base
- 在Base内找名字fcn, 结果找到了int Base::fcn()
- 参数检查,检测调用是否合法,结果合法
- 发现fcn为虚函数,而且我们是通过指针调用的,所以需要确定bpd1的动态类型,发现动态类型为D1,然后又发现D1继承了Base的fcn, 所以最终调用的是Base::fcn。(不要以为hide还会发生, 因为hide只会在名字查找时发生, 而此时名字查找已经在第二步结束了)
最后
不要hide(隐藏)基类的名称!
阅读全文
0 0
- 名字查找与继承
- 关键概念:名字查找与继承
- 名字查找与继承(函数调用的确认)
- C++之:函数调用的名字查找与继承
- 名字查找 与名字空间
- C++继承中的名字查找
- 多重继承与名字二义性
- C++的继承与名字覆盖
- cpp——多重继承——对象名字查找
- 纠错题--类的名字冲突与继承
- C++名字查找与类的作用域
- 【C++】名字查找与类的作用域
- 继承层次中 this,名字查找 导致的成员调用问题
- cpp——类——多重继承——作用域 名字查找
- cpp——类——虚继承——作用域 名字查找
- C++中的名字查找
- C++中的名字查找
- C++中的名字查找
- Redis在Linux下的安装
- Jedis根据日期生成订单号+事务管理
- 3A算法 AF AE AWB
- Redis安装,配置
- list 判断里面判断存不存在元素 如果遍历的同时会修改 就用 ListIterator
- 名字查找与继承
- 走向云计算之HBase模式设计及表设计案例
- Nginx服务器中静态文件cache的处理流程
- mmap()函数分析
- angularjs项目中好用的库
- org.jsoup.HttpStatusException:HTTP error fetching URL. Status=500, URL=******************
- android studio 修改包名
- 海量结构化日志分析系统
- 使用RTL-SDR和Matlab Simulink玩转软件无线电(三)