再提疑问--转换运算符的缺点

绿皮车 2003-05-02 09:19:30
从钱老师的书上,说道转换函数有一个缺点:
“无法定义其类对象运算符操作的真正意义,因为转换之后,只能进行其他类型的运算符操作”----不得其解?
请高人赐教!
...全文
47 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
绿皮车 2003-05-04
  • 打赏
  • 举报
回复
感谢 plainsong,luohualiushui !!!
斑竹 应该坚决kick out像 IConnectionPoint()这样的人!
我们这里是学习的天堂,不是 IConnectionPoint 你发泄的地狱!
短歌如风 2003-05-03
  • 打赏
  • 举报
回复
“自己的类运算符”是什么?
luohualiushui 2003-05-03
  • 打赏
  • 举报
回复
我想钱先生的这句话是说:转换运算符掩盖了类的真正涵义,只能运行其它类型的运算符,即自己的类运算符不能用了
短歌如风 2003-05-03
  • 打赏
  • 举报
回复
我也不太明白,看来钱老师的语言表达能力还是有所欠缺的(我只是在表达我的观点,并无不尊重钱先生的意思,如果因此得罪了什么人,我先在这里表示歉意)。如果是指转换后只能用double运算去完成Rmb的加法运算的话,我觉得这并不是值得一提的缺点。如果你不想用double运算,可以为你的类定义算术运算操作符,它可以和类型转换操作符共存。
我觉得还是象Scott Meyers所说:
如果你要定义一个Rmb的输出函数:
ostream & operator <<(ostream& strm, const Rmb & val
{
strm << Rmb.get_yuan << "元" <<get_jf<<"分";//这里只是一个简单的示例,不太符合规范;这里需要Rmb实现一两个获得成员变量值的函数,我就不写了。
return strm
}
现在你可以用
Rmb a;
...
cout << a;
来达到你的输出要求了。
但如果你一不小心把<<操作符写成了<:
ostream & operator <(ostream& strm, const Rmb & val
{
strm << Rmb.get_yuan << "元" <<get_jf<<"分";
}

Rmb a;
...
cout << a;

这时会出一个“操作符未定义”的编译错误吗?不会,编译器会为你生成这样的代码:
cout << (double)a;
绿皮车 2003-05-03
  • 打赏
  • 举报
回复
plainsong:
《C++程序设计教程》(是不是叫这名字的书太多了) 钱能著 清华大学出版社
P408 18.6节
文中举了一例:
Ex.
#include <iostream.h>
class Rmb
{
public:
Rmb(double val=0.0)
operaotr double()
{
return yuan+jf/100.0;
}

void disp()
{
cout<<(yuan+jf/100.0)<<endl;
}
protected:
unsigned int yuan;
unsigned int jf;
};

Rmb::Rmb(double val)
{
yuan = val;
jf= (val-yuan) * 100+0.5;
}

void main()
{
Rmb d1(2.0),d2(1.5),d3;
d3=Rmb((double)d1+(double)d2);
d3=d1+d2;
d3.disp();
}

然后书中对转换运算符给与评论,说到转换运算符的优缺点
缺点:
无法定义其类对象运算符操作的真正意义,因为转换之后,只能进行其他类型的运算符
操作,如上例中的double加法运算

谢谢你提供的资料!

短歌如风 2003-05-03
  • 打赏
  • 举报
回复
哪本书?上下文是什么?
不查所有的人都看过你说的书的——C++的书太多了。
不过,关于类型转换操作符的缺点,在《More Effective C++》中讲的很明白:

条款五:谨慎定义类型转换函数(节选)

  让我们首先分析一下隐式类型转换运算符,它们是最容易处理的。假设你有一个如上所述的Rational类(短歌注:这是一个有理数类,包含两个double型成员,一个分子,一个分母),你想让该类拥有打印有理数对象的功能,就好像它是一个内置类型。因此,你可能会这么写:

  Rational r(1, 2);

  cout << r; // 应该打印出"1/2"

  再假设你忘了为Rational对象定义operator<<。你可能想打印操作将失败,因为没有合适的的operator<<被调用。但是你错了。当编译器调用operator<<时,会发现没有这样的函数存在,但是它会试图找到一个合适的隐式类型转换顺序以使得函数调用正常运行。类型转换顺序的规则定义是复杂的,但是在这种情况下编译器会发现它们能调用Rational::operator double函数,来把r转换为double类型。所以上述代码打印的结果是一个浮点数,而不是一个有理数。这简直是一个灾难,但是它表明了隐式类型转换的缺点:它们的存在将导致错误的发生。

  解决方法是用等同的函数来替代转换运算符,而不用语法关键字。例如为了把Rational对象转换为double,用asDouble函数代替operator double函数:

  class Rational {
  public:
   ...
   double asDouble() const; //转变 Rational
  }; // 成double

  这个成员函数能被显式调用:

  Rational r(1, 2);

  cout << r; // 错误! Rationa对象没有
   // operator<<

  cout << r.asDouble(); // 正确, 用double类型
//打印r

  在多数情况下,这种显式转换函数的使用虽然不方便,但是函数被悄悄调用的情况不再会发生,这点损失是值得的。一般来说,越有经验的C++程序员就越喜欢避开类型转换运算符。例如在C++标准库(参见条款49和35)委员会工作的人员是在此领域最有经验的,他们加在库函数中的string类型没有包括隐式地从string转换成C风格的char*的功能,而是定义了一个成员函数c_str用来完成这个转换,这是巧合么?我看不是。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧