博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective C++学习之-------若所有参数皆需类型转换,请为此采用non-member函数
阅读量:6176 次
发布时间:2019-06-21

本文共 1723 字,大约阅读时间需要 5 分钟。

假如我们有以下的有理数类:

class Rational {public:    Rational(int numerator = 0, int denominator = 1);    int getnumerator() const;    int getdenominator() const;private:    int numerator;    int denominator;};

在条款19中提到过设计class犹如设计type,也就是说我们的Rational类应该提供类似int类型的功能,因此我们必须添加一些运算符重载函数,标准的教科书函数是这样的,你将自己的重载函数声明为了一个类的成员函数,对一些设计来说这样是可以工作的,比如一下的代码:  

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

作为一个有理数类我们希望他可以和一个整数相乘,于是我们就写出了以下的代码:

result = oneHalf * 2;result = 2 * oneHalf;

第一行的代码能够很好的工作,Oops!!!第二行的地方崩溃了,GCC会给出好几屏的错误提示,这点让人崩溃。下面就来简单分析一下为什么一个第一表达式能够正常运行,而第二个表达式不能正常运行。这次就是发生了所谓的隐士类型转换,编译器发现函数形参是一个Rational而实参是一个int后就给你做了隐士的类型转换,于是乎就有了类似以下的代码,他先用实参构造了一个Rational对象,然后再参与到函数中。

const Rational temp(2);result = oneHalf *temp

对于第二个表达式编译器就无能为力了,2是一个常量他压根就没有this指针也就无法调用类的成员函数。

C++的有些特性很是让人难受,编译器会在你不经意见来一个类型转换。

要实现完全和内置类型一样的乘法,我们有两种手段一种是将运算符重载为类的友元函数:

class Rational {public:    Rational(int numerator = 0, int denominator = 1);    int getnumerator() const;    int getdenominator() const;friend const Rational operator*(const Rational& lhs, const Rational& rhs);private:    int numerator;    int denominator;};

而另外一种方式就是将重载运算符的函数声明为一个non-member函数:

class Rational {public:    Rational(int numerator = 0, int denominator = 1);    int getnumerator() const;    int getdenominator() const;private:    int numerator;    int denominator;};const Rational operator*(const Rational& lhs, const Rational& rhs);

当我看到第二种方式的写法时,对一直将这些函数写成友元函数的我有点小震惊,之后想想这样的设计比起将其声明为友元函数更具有优点,最起码的你不用担心友元函数会破坏你的内部成员了。

这一条给了我一下的启示:  

  1. 这一条给人的第一感觉就是不要固守在别人给你的限定里,该这样做的时候就应该相信自己,有些东西可能违反一些常规,但那是最有效的。

  2.在这一点也体现了提供对原始资源的访问是必须的。这样就可能减少使用friend的次数,避免friend 对数据的破坏是很有必要的。

 

转载于:https://www.cnblogs.com/lzh2nix/archive/2013/05/20/3087964.html

你可能感兴趣的文章
BIOS
查看>>
Elasticsearch之元数据(meta-fields)介绍
查看>>
基于Django+Bootstrap框架,可视化展示内存监控信息
查看>>
Pytorch | BERT模型实现,提供转换脚本【横扫NLP】
查看>>
biostar handbook: 第七周笔记汇总+调整通知
查看>>
涨薪必备|给你一份超详细Spring Boot知识清单
查看>>
YII2 关联查询,不修改search, 使用 GridView::widget 输出
查看>>
DNS服务-了解篇
查看>>
Apache Shiro在web开发安全技术中的应用
查看>>
源码安装MySQL 5.1 GA
查看>>
苹果电脑获取Android Studio的发布版SHA1和开发版SHA1
查看>>
How to troubleshooting RAC Vip Problem
查看>>
jar 命令 打包装class文件的文件夹
查看>>
CentOS 7.2 部署Saltstack
查看>>
centos7下安装MPlayer
查看>>
docker容器中安装vim
查看>>
smokeping 监控
查看>>
NTB EEPROM设置与跨节点数据传输
查看>>
Linux挂载NTFS硬盘错误解决办法
查看>>
IEEE 802.1Q Tunneling
查看>>