Effective_C++:25、避免对指针型别和数值型别进行重载

25、避免对指针型别和数值型别进行重载

1、指针型别和数值型别进行重载的问题

指针保存的是其所指对象的地址,解析时将其变为数值类型。尤其是有时我们把一个空指针定义为0,则当传入一个值为0的参数,若对指针型别和数值型别都进行重载的函数,应当出现编译错误,因为此时编译器不知道0是指针型别还是数值型别。然而,实际上,编译器对于入参为0的情况,会认为其为数值型别,会调用参数为数值型别的函数,并不会出现编译错误。

void f(int x);
void f(string *ps);

2、尝试解决问题

为此,我们尝试定义一个常量,使其可以转换为指针型别和数值型别,则当函数参数为此常量时,即可表现出二义性。

1.如下,NULL可以转换为指针型别,然而需要显示类型转换,即调用类型转换操作符实现。而且调用数值型别的重载函数失败。

void * const NULL = 0;//void*指针可以转换为各类型指针,其本身定义为0
f(NULL);//错误,型别不符
f(static_cast<string *>(NULL);//成功,调用f(string *);

2.尝试用宏定义。在调用指针型别的重载函数时仍需要显示类型转换。

#define NULL 0
#define NULL ((void*) 0)
f(NULL);//成功,调用f(int);
f(static_cast<string *>(NULL));//成功,调用f(string *);

3.一个临时的解决办法。long int 0转换为int与null指针是相同的,不分优先、好坏。此时似乎可以实现让编译器编译错误。然而,当有一个f(long int)与f(string *)重载函数时,此方法就失效了。

#define NULL 0L
f(NULL);//错误,二义性

4.为此,我们希望定义这样一个类,其可以实现将对象隐式转换为所有类型指针,则当调用函数f传入该类对象时,可以将对象隐式转换为任意类型的指针,即解决了上述1、2中需要进行显示类型转换的问题。此时,引入成员函数模板,产生该class的一些成员函数。

class NullClass {
public:
    template<class T>
    operator T*() const { return 0; }
};
const NullClass NULL;

优化一下,没必要给出class名称,不需要一个以上的类对象;添加可使其隐式转换为指向类成员的指针的成员函数模板;最后,NULL是指针值,不允许取地址。

const
class {
public:
    template<class T>
    operator T*() const
    { return 0; }
    template<class C, class T>
    operator T C::*() const
    { return 0; }
private:
    void operator&() const;
} NULL;

3、避免对指针型别和数值型别进行重载

以上,我们定义了NULL来实现传入NULL时隐式类型转换为指针型别,来让编译器实现入参的二义性而编译错误。然而,回到最初的问题,若传入0,编译器仍然认为他是数值型别。

因此,最好的办法就是避免对指针型别和数值型别进行重载。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值