Effective C++第七章-模板和泛型编程之需要类型转换时请为模板定义非成员函数

需要类型转换时请为模板定义非成员函数

在条款24中,

class Rational
{
public:
    const int numerator() const {return n;}
    const int denominator() const {return d;}
privateint n,d;
};
const Rational operator*(const Rational& lhs,const Rational& rhs)//非成员函数,
{
    return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
}
Rational oneFourth(1,4);
Rational result;
result = oneFourth * 2;
result = 2 * oneFourth;
//只有当参数被列于参数列内,这个参数才是隐式类型转换的合格参与者

但如若考虑template

template<typename T>
class Rational
{
public:
    const T numerator() const {return n;}
    const T denominator() const {return d;}
private:
    T n,d;
};
template<typename T>
const Rational<T> operator*(const Rational<T>& lhs,const Rational<T>& rhs)//非成员函数,
{...}
Rational<int> oneFourth(1,4);
Rational<int> result = oneFourth * 2;//wrong????

发生错误的原因在于:

​ 在条款24中的代码中,编译器知道调用的函数是接受两个Rational参数的operator*。但是在后面的模板代码中,第一个参数是Rational< int >(oneFourth),第二个是int(2),编译器只知道可以具现化一个名为operator *并接受两个Rational< T >参数的函数,此时,即使通过构造函数可以实现内置类型到对应的模板类的隐式转换(例如,int->Rational< int >),然而,template实参推导过程中并不考虑采纳“通过构造函数发生的”隐式类型转换。因此编译器不知道应该调用哪个函数。

解决方法:令Rational< T >class声明适当的operator* 为其friend函数:

template<typename T>
class Rational
{
    friend const Rational operator*(const Rational& lhs,const Rational& rhs)
    {
        return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
    }
};
Rational<int> oneFourth(1,4);
Rational<int> result = oneFourth * 2;//可以编译通过。

说明:在一个class template内,template名称可被用来作为“template和其参数”的简略表达方式,所以Rational< T >可以写为Rational。因为当oneFourth 被声明为一个Rational< int > ,class Rational< int >被具现化,而作为过程中的一部分,friend函数operator*(接受Rational< int >参数)也被声明出来,身为一个函数而非函数模板,因此编译器可在调用它时使用隐式转换函数。

许多编译器实质上会强迫你把所有template定义式放进头文件中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值