c++编译时多态(1)

函数重载

三个阶段: 名称查找, 模板函数处理, 重载决议

前两个阶段得到候选集, 最后一个阶段选出最合适的版本

namespace animal
{
    struct Cat{};
    void feed(Cat *foo, int);
}

struct CatLike
{
    CatLike(animal::Cat *);
};
template<typename T>
void feed(T *obj, double);
template<>
void feed(animal::Cat *obj, double d);

以下会调用哪一个版本?

animal::Cat cat;
feed(&cat, 1);

以下分析

名称查找

成员函数名称查找: 通过. ->调用时, 在对应的成员类里查找

限定名称查找: 通过::调用时进行的查找

未限定名称查找: 可以通过参数依赖查找规则查找

注意参数依赖查找规则(ADL): 除了通常的作用域外, 实参类型对应的命名空间也在查找范围内

如下, 由于参数v的类型vector<int>在std命名空间里, 所以只调用sort却成功查找到了std::sort

#include "vector"
int main()
{
    std::vector<int> v;
    sort(v.begin(),v.end());
}

考虑另一种情形std::cout<<" " , 对std::cout调用的operator<<也没有注明命名空间,

操作符重载等场景中, 此规则大大简化了调用

ADL规则仅在未限定名称查找时有效(函数名左边不能有 . -> ::), 可以手动为函数添加括号禁用ADL规则

#include "vector"
int main()
{
    std::vector<int> v;
    (sort)(v.begin(),v.end());  //错误, sort未定义
}

上面中sort未定义

经过查找后剩下的候选函数

void animal::feed(Cat *foo, int);

void feed(CatLike);

template<typename T>
void feed(T *obj, double);

模板函数处理

对以下进行实例化

template<typename T>
void feed(T *obj, double);

 得到

template<animal::Cat>
void feed(animal::Cat *obj, double);

不过, 若模板参数推导与替换失败, 则会删除该候选函数

template<typename T>
void feed(T *obj, typename T::value_type);

实例化出

template<animal::Cat>
void feed(animal::Cat *obj, animal::Cat::value_type);

其中Cat并没有value_type这个成员变量, 因此替换失败, 删除该候选集, 但此时还没有错误(SFINAE机制), 当最后候选集为空时才发生编译错误

重载决议

剩下的候选集

void animal::feed(Cat *foo, int);

void feed(CatLike);

template<animal::Cat>
void feed(animal::Cat *obj, double);

由于第二个版本参数不匹配, 最后只剩下

void animal::feed(Cat *foo, int);

template<animal::Cat>
void feed(animal::Cat *obj, double);

最后根据规则决策最佳函数

1, 类型最匹配, 转换最少的

2, 非模板函数优于模板函数

3, 若多于两个模板实例, 最具体的实例最佳

根据规则1, 调用feed(&cat,1);将使用第一个版本

而调用feed(&cat,1.0);将使用第二个版本

若候选集为

void animal::feed(Cat *foo, int);

template<animal::Cat>
void feed(animal::Cat *obj, int);

仍是调用feed(&cat,1);, 根据规则2,  将使用第一个版本(非模板函数)

若候选模板函数为

template<typename T>
void feed(T *obj, double);
template<typename T&g
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值