c++名字查找原则

如果在声明函数的参数时使用了一个类,那么在查找匹配的函数名字时,编译器会在包含参数类型的名字空间中也进行查找。

#include "stdafx.h"
#include <iostream>
using namespace std;
namespace lx1{
    class Point3d    {
        public:
        Point3d (double dx, double dy, double dz): m_dX(dx), m_dY(dy), m_dZ(dz){}
        double getX() const { return m_dX; };
        double getY() const { return m_dY; };
        double getZ() const { return m_dZ; };
    	private:
        double m_dX;
        double m_dY;
        double m_dZ;
    };
    void TestPoint(const Point3d &pt){cout << "Output from lx1::TestPoint()." << endl;}
}
namespace lx2{
    void TestPoint(const lx1::Point3d &pt){cout << "Output from lx2::TestPoint()." << endl;}
    void ShowPoint3d(const lx1::Point3d &pt){
        TestPoint(pt);
        cout << "X: " << pt.getX() << endl;
        cout << "Y: " << pt.getY() << endl;
        cout << "Z: " << pt.getZ() << endl;
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

1>c:\code\test1\cmd\cmd.cpp(42): error C2668: 'lx2::TestPoint' : ambiguous call to overloaded function
1>          c:\code\test1\cmd\cmd.cpp(35): could be 'void lx2::TestPoint(const lx1::Point3d &)'
1>          c:\code\test1\cmd\cmd.cpp(27): or       'void lx1::TestPoint(const lx1::Point3d &)' [found using argument-dependent lookup]
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).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值