`
阿尔萨斯
  • 浏览: 4173304 次
社区版块
存档分类
最新评论

C++中的名字查找

 
阅读更多
<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>
原文:http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!248.entry

Vijay Visana最近发邮件问我两个问题。内容如下(为了更适合阅读,我做了简单修改。译者在此基础上又做了修改):

我在C++的多继承上遇到了很大麻烦。

如图1AB1B2为纯抽象类;CB1B2多继承,且实现了全部父类的抽象方法。

现在:

C* p = new C;

p->Method_of_A(); //B1B2都能得到被调用方法,为什么编译器不报“二义性”(ambiguity)错误呢?

而按图2结构实现继承关系后:

B4* p = new C;

p->Method_of_A();

编译器(VC++)认为有二义性。经调试我发现编译过程中使用了“adjustor thunk”(译者注:具体请参看http://blog.sina.com.cn/u/491874bb010004xqStan Lippman的《Inside the C++ Object Model》)。希望您能解答这两个问题,以帮助我更好理解C++(更确切的说是VC++)中的MI(多继承)机制。

好,我们深入研究下这个问题。

上述编译器行为的差异,与继承关系的复杂度、vtable以及adjustor thunk并无直接关系,它其实就是一个名字查找(name lookup)过程(以本例而言,就是查找方法“Method_of_A”)。

C++中,函数编译时检查过程如下:

第一步,执行名字查找(name lookup):在调用类中查找,并生成候选列表;若候选列表为空,再扩大查找范围(如名字空间内,或父类);如此循环。如果最终无结果,那么抱歉,就会提示你“名字未能找到”;否则,编译器跳到第二步。

第二步,执行重载辨别(overload resolution):如果第一步得到的候选者个数大于一,编译器将以传递给函数的参数及其类型为依据,尝试找到最佳答案。如果无法据此确定最优者,就会报告“存在二义性调用”。

第三步,可见性检查(accessibility checking):编译器检查是否可真正执行调用(比如,被调用函数是否是私有的)。

关于这方面的更详细资料,可参看我如下文章:

Namespaces and the Interface Principle

What's In a Class? - The Interface Principle

GotW #30: Name Lookup

总而言之一句话,上述三个过程,都实现于对象的静态类型基础上,与实例无关。

问题1

C* p = new C;

p->Method_of_A();

名字查找就只会在C中进行,根本不会达到A,实际就是直接调用C::Method_of_A

而在问题2中:

B4* p = new C;

p->Method_of_A();

使用的对象类型是B4,而B4本身没有提供Method_of_A,因此会到其父类B1B2中查找,结果找到两个,且不能通过重载辨别实现优化,因此报告存在二义性。

译者注:此问题虽然简单,但工作繁忙的Herb Sutter仍拨冗撰文详细作答,足显其谦虚、热心和认真的品质,值得我们学习。




分享到:
评论

相关推荐

    C++利用 _findfirst与_findnext查找文件的方法

    在C++中我们要如何查找文件呢?我们需要一个结构体和几个大家可能不太熟悉的函数。这些函数和结构体在的头文件中,结构体为struct _finddata_t ,函数为_findfirst、_findnext和_fineclose。具体如何使用,下面来...

    c++褊写的二分法查找程序

    c++二分法查找,先进行冒泡排序后查找 int main() { int num[100]; int ncount; while (1) { cout输入数据元素个数(输入非正数即退出程序):"; cin&gt;&gt;ncount; if(ncount) exit(1); Input(num,ncount); //...

    Exceptional C++中文版

    全书共分8章,包括范型程序设计与C++标准库、异常安全性的问题与技术、类的设计与继承、编译器防火墙和Pimpl惯用法、名字查找名字空间和接口规则、内存管理、误区陷阱以及错误的惯用法等。本书内容深入,论证严谨,...

    C++模板二段名字查找方法

    下面小编就为大家带来一篇C++模板二段名字查找方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    浅谈C++继承中的名字查找

    下面小编就为大家带来一篇浅谈C++继承中的名字查找。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    exceptional c++:47个c++工程难题、编程问题和解决方案(英文版)

    条款31:名字查找与接口规则——之一 148 条款32:名字查找与接口规则——之二 152 条款33:名字查找和接口规则——之三 162 条款34:名字查找与接口规则——之四 167 6 内存管理 176 条款35:内存管理——之一...

    C++ Primer第四版【中文高清扫描版】.pdf

    类作用域中的名字查找 382 12.4 构造函数 385 12.4.1 构造函数初始化式 387 12.4.2 默认实参与构造函数 391 12.4.3 默认构造函数 392 12.4.4 隐式类类型转换 393 12.4.5 类成员的显式初始化 396 12.5 友元 396 12.6 ...

    c++API 函数库

    1. API 之网络函数 WNetAddConnection 创建同一个网络资源的永久性...WNetGetUniversalName 获取网络中一个文件的远程名 称 WNetGetUser 获取一个网络资源用以连接的名字 WNetOpenEnum 启动对网络资源进行枚举的过程

    C++编程思想 例子和叙述讲解C++编程

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

    C++编程思想 编程

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

    免费下载:c++编程思想(中文)

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

    C++编程思想.pdf

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子...

    C++编程-数据结构与程序设计方法[美.D.S.Malik][中译本]

    8. 用户自定义简单数据类型、名字空间和string类型 9. 数组和字符串 10.递归 11.结构 12.类和数据抽象 13.继承和组成 14.指针、类、表及虚函数 15.重载与模板 16.链表 17.栈和队列 18.查找和排序算法 19.二叉树 20....

    c++ 编程思想 (高清pdf)

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

    Thinking in C++高清版

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

    C++ 语言 详细教程电子版

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

    C++ 编程思想 打印版 pdf

    6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 ...

Global site tag (gtag.js) - Google Analytics