C++ 中的重载运算符 +
Overloading operator+ in c++
我对考试练习任务之一有一点问题。这是一段文字:
类 MyFloat 有一个私有变量浮点数。您必须编写将启用下一行代码的方法: 我的浮点数 x = 3.5; MyFloat y = x + 3.2 浮点数 z = 3.4 + y
我写了这段代码:
#include <iostream>
#include <Windows.h>
using namespace std;
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
MyFloat operator+(MyFloat x)
{
float result;
result = x.num + this->num;
return result;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4 + y;
system("PAUSE");
}
我在这一行中得到错误:
float z = 3.4 + y;
它说:
错误 C2677:二进制"+":未找到采用类型为"MyFloat"的全局运算符(或者没有可接受的转换)
我该怎么办?如何解决这个问题???
operator+
实现为非成员友元函数,MyFloat operator+(MyFloat x, MyFloat y)
2 个参数。
为什么它在当前版本中不起作用?因为成员运算符函数是在运算符左侧的对象上调用的。在左侧的情况下,您有整数文字,它不是一个对象MyFloat operator+(MyFloat x)
因此缺少成员函数。
运算符的非成员变体是对称的,不需要左侧是对象。对称性很重要,因为正如您在示例中所看到的operator+
它不像我们习惯于在数学中思考的那样对称
编辑:但正如卡西奥·内里在评论中指出的那样,这仍然不够。为什么?请看他的回答,但简而言之:你有歧义问题。如果你像这样手动铸造,你可以使用他的解决方案或这个解决方案:float z = 3.4f + static_cast<float>(y);
这很丑陋。您可以使用其他转换:float z = MyFloat(3.4f) + y
如果您提供MyFloat::operator float
转换。
解决相同歧义问题的另一种解决方案:在 C++11 中,您可以使用自己的后缀文字(类似于内置浮点数的f
前缀,例如 3.4_f
;(下划线表示此后缀文本是用户定义的)。示例实现(假设您实现了从MyFloat
到float
和向后的转换运算符:
MyFloat operator "" _f(long double val) {
return MyFloat(static_cast<float>(val)); }
int main() {
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4_f + y;
}
这可能是一个解决方案:
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
operator float() const {
return num;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2f;
float z = 3.4f + y;
}
最初,我也想让MyFloat operator+(MyFloat, MyFloat)
成为非会员朋友功能,但它仍然没有发挥作用
float z = 3.4 + y;
进行编译。原因是3.4 + y
的类型为 MyFloat
,因此您无法将其分配给float z
,除非您提供从 MyFloat
到 float
的转换运算符。然后,3.4f + y
变得模棱两可(至少对于VS 2010),因为它可以调用MyFloat operator+(MyFloat, MyFloat)
,也可以将y
转换为float
并使用内置运算符+
进行float
。
你只有 MyFloat + float 操作,你也需要定义 float + MyFloat 操作。它们是不一样的。
将此添加到您的公共函数中:
friend float operator+ (const float& lhs, const MyFloat& rhs);
而这个课外:
float operator+ (const float& lhs, const MyFloat& rhs) {
return lhs + rhs.num;
}
注意:根据CassioNeri的评论编辑。
虽然您可以继续定义"强制浮动"方法的答案,但我相信为了您自己的利益,您最好开始使用您的公共 API 来实现其他行为。
一般来说,简单的"强制转换"是行不通的(例如,如果MyFloat
MyMatrix
会发生什么?
下面的方法当然更冗长,但它强调你应该"吃自己的食物",这意味着你应该尝试基于你自己的公共接口实现额外的行为,而不是一堆晦涩的隐式强制转换或friend
函数。如果您使用自己的 API:您将了解其局限性,并且如果您进行修改,可能会节省主类的重新编译。
此外,假设您要计算对类的访问次数(或以其他方式控制对基础值的访问):使用强制转换运算符,您需要在 operator float()
和 float value()
中复制代码。
所以,这是我的拙见建议,它看起来更长,但就我的口味而言,更好地反映了OO设计原则。
#include<iostream>
class MyFloat {
public:
MyFloat(float value):
m_value(value) { }
float value() const {
return m_value;
}
private:
float m_value;
};
// Eat your own food: implement functions using your public interface
// until proven need to do otherwise. This will help you assess the
// usability of your API.
float operator+(const MyFloat& lhs, const MyFloat& rhs) { return lhs.value() + rhs.value(); }
float operator+(const MyFloat& lhs, float rhs) { return lhs.value() + rhs; }
float operator+(float lhs, const MyFloat& rhs) { return lhs + rhs.value(); }
// See, now I can define another operator without need to recompile my
// class (this could have been placed in another file)
std::ostream& operator<<(std::ostream& os, const MyFloat& mf) {
os<<"MyFloat("<<mf.value()<<")";
return os;
}
int main() {
MyFloat x = 3.5; // would not work if I had declared the constructor as "explicit"
MyFloat y = x + 3.2;
MyFloat z = 3.4 + y;
std::cout<<x<<", "<<y<<", "<<z<<std::endl;
}
输出(用g++ example.cpp -Wall -Wextra
编译):
MyFloat(3.5), MyFloat(6.7), MyFloat(10.1)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- <T> 通过模板化运算符重载将 std::complex 乘以双倍
- C++20概念:需要运算符重载
- 使用赋值运算符重载从类中返回jobject
- 在运算符重载定义中使用成员函数(const错误)
- 字节到位运算符重载C++
- 为什么在运算符重载时需要参考?
- 类中 c++ 的运算符 + 重载
- 算术复合运算符重载为非成员
- 运算符重载 (+),用于添加两个具有 C++ 的数组
- 交换运算符 + 重载会导致无限递归
- 如何理解新的运算符重载?
- 向量保持复数的运算符重载
- 如何创建运算符重载?
- 链接列表运算符重载没有打印出我想要的内容
- C++:需要帮助了解运算符重载错误
- 使用模板化运算符重载 XOR 运算符失败
- 如何确保接受的C++模板类型使运算符重载?
- 运算符重载使用运算符+添加类模板