若所有参数需类型转换,采用non-member函数(Effective_C++(24))

本文深入探讨了如何设计一个支持隐式类型转换的有理数类,以便于与其他类型进行运算。重点分析了成员函数与非成员函数在实现隐式类型转换时的不同表现及原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、考虑下面问题

设计一个class表示有理数,它应该支持隐式类型转换,虽然我们说支持隐式类型转换通常是个不好的主意。这是为了我们设计的类可以和内置类型进行运算。例如和整型:

class Rational {
 pbulic:
  Rational(int numerator = 0, int denominator = 1); //注意这个构造函数不为explicit
  int numerator() const;
  int denominator() const;   //两个接口 提供对成员的访问
 priavte:
  .... 
 };

当我们想这个class可以支持运算如加法等。operator*()函数声明为member函数,还是声明为non-member函数?


(1)声明为 member函数

class Rational {
 public:
  .....
  const Rational operator* (const Rational& rhs) const;
 };

这个设计能使类的对象很好的运算,例如:

 Rational oneEighth(1,8);
 Rational oneHalf(1,2);
 Rational result = oneHalf * oneEighth; 

但是,当对象很一个内置型进行运算时,便会出现问题:

 result = oneHalf * 2;    //很好
 result = 2 * oneHalf;    //错误 

为什么会这样,考虑上面的等价函数调用形式:

 result = oneHalf.operator*(2);  //成功
 result = 2.operator*(ontHalf);  //错误

为什么第一个可以成功呢?2也不是一个Rational类型的对象。因为编译器为这个2进行了隐式类型转换。 为什么第二个没有发生隐式类型转换了?这是因为第一个调用2是作为参数,而第二个不是。

可是作为member函数只能接收一个参数,而我们这里需要两个参数都需要能发生隐式类型转换。所以唯一的办法就是使用non-member函数。


(2) non-member函数实现

 class Rational { ... };
 const Rational operator* (const Rational& lhs, const Rational& rhs) //一个non-member函数,并没有声明为友元
 {
  return Rational(lhs.numerator() * rhs.numerator(),
   lhs.denominator()* rhs.denominator());
 }

 ......

 result = oneHalf * 2;    //很好
 result = 2 * oneHalf;    //通过编译

该把这个函数声明为friend函数?请记住无论何时如果你可以避免friend函数就该避免破坏封装性


(3)总结:
如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.


参考:Effective C++ 3rd(侯捷译)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值