C++编译器的函数编译流程
来源:互联网 发布:西工大编程网址 编辑:程序博客网 时间:2024/06/05 12:43
C++中的类型查找过程相对简单,基本上就是名字查找,这里不再介绍。对于 .cpp 文件中调用的一个函数 ( 或成员函数 ), 编译器主要做了下面三件事情 :
1 、名字查找 。
先在所在编译单元中可见名字实体中进行名字查找 。
(1) 类成员函数优先 ( 对象所在的类 -》 基类 )。 一经找到就停止查找 。
(2 )如果没有 ,在相应的名字空间中做进一步的搜索 ;
(3) 如果还没有 , 会根据函数参数所在的名字空间中查找 (keoning 查找 )。
2 、重载决议 。 根据所找到的名字进行重载决议 , 根据参数最匹配原则选择相应的函数 。
3、可访问性检查 。 用以确定被选中的函数是否可被调用 。
说明 :
1) 根据第一条 , 显然 , 如果类型想和非成员函数一起工作 , 那么它们应该放在同一个名字空间中 。 比如 , 一般类型的重载运算符和参数类型放在同一个头文件中/或者同一个名字空间下 。
2) 函数特化模板不参与重载决议 , 因此 , 如果想运用某个函数的特化 , 最好的方法是重载该函数 , 在实现中采用该特化来工作 。
3) 重载决议发生在可访问性检查之前 。 因此 , 如果私有函数不幸参与了重载 , 并且被选中 , 最终也会出现无法访问的编译提示 。 这常常隐含二义性 , 这样的设计本身也不合理 。 换句话说 , 私有参数 , 在名字查找和重载时并非是 ” 私有的 ”。
以 c.Twice( 21 )的函数调用为例:
a) 名字查找:编译器会首先寻找一个至少包含一个名字为 Twice 的实体作用域(类,文件,或者名字空间),并将候选函数放入候选实体列表。例子中,编译器首先从对象 c 所在类实体中进行查找,找到就停止;如果没找到就会依次在其基类和外围的名字空间中查找,直到找到一个至少含有一个候选函数的作用域。
两点需要注意:
1) 只要找到一个实体就停止查找,所以并非所有的同名函数都会被考虑;
2) 参数所在名字空间也属于查找范围(keoning 准则) 。
b) 重载决议:从所找到的候选重载函数列表中选出唯一最佳匹配 。如不唯一,就存在二义性。
注意:
1) 这是基于名字查找结果的;
2) 特化的模板函数不参与重载。
c) 可访问性检查:确定所选出的函数是否可访问。这是最后一步,晚于重载决议。
文章中的规则非常重要,理解后,很多C++的编译问题就自然解决了。后面将会有进一步的文章来介绍:如何确定C++每个编译单元(CPP文件)中的可见名字(与名字查找相关);Keoning查找详解; 重载 (Overload) 和虚函数的重实现 (override).
1 、名字查找 。
先在所在编译单元中可见名字实体中进行名字查找 。
(1) 类成员函数优先 ( 对象所在的类 -》 基类 )。 一经找到就停止查找 。
(2 )如果没有 ,在相应的名字空间中做进一步的搜索 ;
(3) 如果还没有 , 会根据函数参数所在的名字空间中查找 (keoning 查找 )。
2 、重载决议 。 根据所找到的名字进行重载决议 , 根据参数最匹配原则选择相应的函数 。
3、可访问性检查 。 用以确定被选中的函数是否可被调用 。
说明 :
1) 根据第一条 , 显然 , 如果类型想和非成员函数一起工作 , 那么它们应该放在同一个名字空间中 。 比如 , 一般类型的重载运算符和参数类型放在同一个头文件中/或者同一个名字空间下 。
2) 函数特化模板不参与重载决议 , 因此 , 如果想运用某个函数的特化 , 最好的方法是重载该函数 , 在实现中采用该特化来工作 。
3) 重载决议发生在可访问性检查之前 。 因此 , 如果私有函数不幸参与了重载 , 并且被选中 , 最终也会出现无法访问的编译提示 。 这常常隐含二义性 , 这样的设计本身也不合理 。 换句话说 , 私有参数 , 在名字查找和重载时并非是 ” 私有的 ”。
以 c.Twice( 21 )的函数调用为例:
a) 名字查找:编译器会首先寻找一个至少包含一个名字为 Twice 的实体作用域(类,文件,或者名字空间),并将候选函数放入候选实体列表。例子中,编译器首先从对象 c 所在类实体中进行查找,找到就停止;如果没找到就会依次在其基类和外围的名字空间中查找,直到找到一个至少含有一个候选函数的作用域。
两点需要注意:
1) 只要找到一个实体就停止查找,所以并非所有的同名函数都会被考虑;
2) 参数所在名字空间也属于查找范围(keoning 准则) 。
b) 重载决议:从所找到的候选重载函数列表中选出唯一最佳匹配 。如不唯一,就存在二义性。
注意:
1) 这是基于名字查找结果的;
2) 特化的模板函数不参与重载。
c) 可访问性检查:确定所选出的函数是否可访问。这是最后一步,晚于重载决议。
文章中的规则非常重要,理解后,很多C++的编译问题就自然解决了。后面将会有进一步的文章来介绍:如何确定C++每个编译单元(CPP文件)中的可见名字(与名字查找相关);Keoning查找详解; 重载 (Overload) 和虚函数的重实现 (override).
- C++编译器的函数编译流程
- C++编译器的函数编译流程揭秘
- C++编译器的函数编译流程
- C++编译器的函数编译流程
- 揭秘:C++编译器的函数编译流程
- C++编译器的函数编译流程
- C++编译器的函数编译流程
- [C++再学习系列] C++编译器的函数编译流程
- C++ 编译器的函数编译流程揭秘(转)
- 为什么c++程序调用c编译器编译的函数需要在调用前加上extern“C”
- 在C++中调用被C编译器编译后的函数,为什么要加extern "C"
- 为什么在C++里调用被C编译器编译的函数,要加extern "c"
- 在C++中调用C编译器编译过的函数时,为什么要使用"extern C"?
- 面试---在C++ 中调用被 C 编译器编译后的函数,加 extern “C”
- c++程序调用被C编译器编译后的函数为什么要加extern "C"
- C编译器的八个编译阶段
- C语言的编译器及编译过程
- C/C++的编译器|编译环境
- 链接脚本语言和C/C++之间的最好的工具:SWIG
- Android入门:ListView(SimpleAdapter实现)
- 操作系统类型(下篇)
- 工厂模式
- FLASH多文件批量上传应用(第三版)
- C++编译器的函数编译流程
- 最佳实践 ADO.NET实用经验
- trie树--详解
- Android入门:ListView(SimpleCursorAdapter实现)
- .mdf 和.LDF导入SQL 2005问题
- 复合与存取方法
- .com和.exe
- 参考这样的人生 --- 继续我的编程人生
- 吉林大学ACM总结(fennec)(附动态规划总结)