营销型网站单页面,自己怎做网站后台,360网址导航上网,苏州网站托管经常在对象上执行如相加#xff0c;比较#xff0c;文件传输等操作。例如#xff0c;spreadsheet只有在可以在上面执行自述运算才有用#xff0c;比如对整行的单元格求和。所有这些都可以通过重载操作符来完成。 许多人发现操作符重载的语法复杂而令人迷惑。至少一开始是这… 经常在对象上执行如相加比较文件传输等操作。例如spreadsheet只有在可以在上面执行自述运算才有用比如对整行的单元格求和。所有这些都可以通过重载操作符来完成。 许多人发现操作符重载的语法复杂而令人迷惑。至少一开始是这样。真实情况是想让事情更简单。在本节你会发现那并不意味着写类时更简单只是使用类时更简单。关键点是让新类与内建像int与double这样的类型一样简单使用来使对象相加要比记住不管是add()或是sum()这样的成员函数名要容易多了。 注意作为服务给客户提供类的操作符重载。 在这一点上你可能会想到底哪些操作符可以重载呢答案是几乎所有--甚至是你没有听说过的。本章会浮光掠影地简单涉及一下赋值操作符在本章的前面 已经解释过了而本节要介绍的是基础的算术操作符缩写的算术操作符以及比较操作符。重载流插入与释放操作符也比较有用。还有有一些麻烦但是又比较有趣的东东一开始你可能并不想用操作符重载来做。在标准库中大量使用操作符重载。以后我们会解释怎么以及什么时候重载其他的操作符。以及标准库方面的内容。
1、例子SpreadsheetCell的另外内容的实现 在真正的面向对象的编程风格中SpreadsheetCell对象应该能够把自己与其它SpreadsheetCell对象相加。将一个单元格与另一个单元格相加生成结果为第三个单元格。这并不会改变原来的任一单元格。SpreadsheetCell相加的意思就是单元格值的相加。
1.1、第一次尝试加成员函数 可以为SpreadsheetCell类像这样声明与定义add()成员函数
export class SpreadsheetCell
{
public:SpreadsheetCell add(const SpreadsheetCell cell) const;// Omitted for brevity
}; 该成员函数将两个单元格相加返回一个新的第三个单元格 其值是前两个的和。声明为const并且 用一个const SpreadsheetCell的引用是因为add()不会改变任意一个源单元格。下面是其实现
SpreadsheetCell SpreadsheetCell::add(const SpreadsheetCell cell) const
{return SpreadsheetCell { getValue() cell.getValue() };
} 可以像这样来使用add()成员函数
SpreadsheetCell myCell { 4 }, anotherCell { 5 };
SpreadsheetCell aThirdCell { myCell.add(anotherCell) };
auto aFourthCell { aThirdCell.add(anotherCell) }; 这也可以达到目的但是有一点儿繁琐我们可以做得更好。
1.2、第二次尝试重载操作符作为成员函数 用加号类似于两个int或者两个double的方式来将两个单元格相加会比较方便--有点儿像下面这样
SpreadsheetCell myCell { 4 }, anotherCell { 5 };
SpreadsheetCell aThirdCell { myCell anotherCell };
auto aFourthCell { aThirdCell anotherCell }; c允许你写自己的加号版本叫做加操作符来正确地作用于类。为了做到这一点写一个名字叫做operator的成员函数看起来像这样
export class SpreadsheetCell
{
public:SpreadsheetCell operator(const SpreadsheetCell cell) const;// Omitted for brevity
}; 注意在operator与加号之间可以加入空格。例如可以将operator写成operator 。我们还是使用没有空格的风格。 重载的operator成员函数的定义与add()成员函数的实现是一样的
SpreadsheetCell SpreadsheetCell::operator(const SpreadsheetCell cell) const
{return SpreadsheetCell { getValue() cell.getValue() };
} 现在你就可以使用前面展示的加号操作符来将两个单元格 相加了。 我们还是比较习惯于这种语法。不要过于担心奇怪的成员函数名operator----它就是一个类似于foo或add的名字而已。为了理解语法的其余部分它有助于理解真实发生的情况。当c编译器解析程序时遇到比如说,-,,或这样的操作符它会用operator,operator-,operator,或operator这样的名字来找函数或成员函数特别是带有适合的参数的。例如当编译器看到下面的代码行它会尝试在SpreadsheetCell类中去找成员函数名字为operator接受另一个SpreadsheetCell作为参数或者在本章后面会讨论到的接受两个SpreadsheetCell参数的全局函数名字叫做operator
SpreadsheetCell aThirdCell { myCell anotherCell }; 如果SpreadsheetCell类包含这样一个operator成员函数上面的行就会被翻译成这样
SpreadsheetCell aThirdCell { myCell.operator(anotherCell) }; 注意operator没有要求其参数的对象是与它所写的类是同一种类型。你可以写一个SpreadsheetCell的operator拿一个Spreadsheet去加到SpreadsheetCell。这对于程序员是讲不通的但是编译器是允许的。下一节会给出一个SpreadsheetCell的operator接受double值的例子。 也要注意可以让operator返回你想的任何类型。然而应该遵循最少惊奇的原则也就是说operator的返回类型通常应该是用户想要的。
1.2.1、隐式转换 令人吃惊的是一旦写完前面所示的operator不但可以将两个单元格相加也可以将一个单元格加到一个string_view一个double或一个int下面是一些例子
SpreadsheetCell myCell { 4 }, aThirdCell;
string str { hello };
aThirdCell myCell string_view{ str };
aThirdCell myCell 5.6;
aThirdCell myCell 4; 这些代码能跑的原因是编译器会比尝试找到合适的operator的所指的正确的类型更多的工作。编译器也会尝试找到合适的类型转换。SpreadsheetCell类有转换构造函数将double或string_view转换成一个SpreadsheetCell。在前面的例子中当编译器看到一个SpreadsheetCell尝试将自身加到一个double上它发现SpreadsheetCell构造函数用了double并且 构建了一个临时的SpreadsheetCell对象传递给operator。同样的当编译器看到代码行尝试将一个SpreadsheetCell加到一个string_view上时它会调用string_view SpreadsheetCell构造函数生成一个临时的SpreadsheetCell传递给operator。 要记住虽然使用隐式转换构造函数可以效率不高因为要生成临时对象。在这个例子中为了避免隐式构建与double相加可以写如下的第二个operator:
SpreadsheetCell SpreadsheetCell::operator(double rhs) const
{return SpreadsheetCell { getValue() rhs };
}