C++同一运算符的多个运算符重载

发布于 2024-09-07 20:27:07 字数 905 浏览 5 评论 0原文

我知道我可以通过生成代码并查看它是否可以编译来轻松地回答这个问题。但由于我找不到类似的问题,我认为这是值得分享的知识。 假设我正在重载 MyClass 的 + 运算符。我可以多次超载吗?不同类型的过载不同。像这样:

class MyClass{
...
inline const MyClass operator+(const MyClass &addend) const {
    cout<<"Adding MyClass+MyClass"<<endl;
    ...//Code for adding MyClass with MyClass
}
inline const MyClass operator+(const int &addend) const {
    cout<<"Adding MyClass+int"<<endl;
    ...//Code for adding MyClass with int
}
...
};
int main(){
    MyClass c1;
    MyClass c2;
    MyClass c3 = c1 + c2; 
    MyClass c4 = c1 + 5;
}
/*Output should be:
  Adding MyClass+MyClass
  Adding MyClass+in*/

我想这样做的原因是我正在构建一个我想要尽可能优化的类。性能是我最关心的问题。因此,在运算符+重载函数内部进行强制转换和使用 switch case 不是一种选择。如果您注意到的话,我将这两个重载都内联了。让我们假设编译器确实内联了我的重载,然后在编译时就预先确定了将运行哪些代码,并且我保存了对函数的调用(通过内联)+一个复杂的 switch case 场景(实际上,将会有+ 运算符的 5+ 重载),但我仍然能够使用基本算术运算符编写易于阅读的代码。 那么,我会得到想要的行为吗?

I know I can answer this question easily for myself by generatin the code and see if it compiles. But since I couldn't find a similar question, I thought it's knowledge worth sharing.
Say I am overloading the + operator for MyClass. Can I overload it multiple times. Different overload for different types. Like this:

class MyClass{
...
inline const MyClass operator+(const MyClass &addend) const {
    cout<<"Adding MyClass+MyClass"<<endl;
    ...//Code for adding MyClass with MyClass
}
inline const MyClass operator+(const int &addend) const {
    cout<<"Adding MyClass+int"<<endl;
    ...//Code for adding MyClass with int
}
...
};
int main(){
    MyClass c1;
    MyClass c2;
    MyClass c3 = c1 + c2; 
    MyClass c4 = c1 + 5;
}
/*Output should be:
  Adding MyClass+MyClass
  Adding MyClass+in*/

The reason I want to do this is that I am building a class that I want to be as optimized as possible. Performance is the biggest concern for me here. So casting and using switch case inside the operator + overloaded function is not an option. I f you'll notice, I made both the overloads inline. Let's assume for a second that the compiler indeed inlines my overloads, then it is predetermined at compile time which code will run, and I save the call to a function (by inlining) + a complicated switch case scenario (in reality, there will be 5+ overloads for + operator), but am still able to write easily read code using basic arithmetic operators.
So, will I get the desired behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鹿港小镇 2024-09-14 20:27:07

是的。


这些运算符函数只是具有特殊名称operator@ 的普通函数。没有限制它们不能超载。事实上,iostream使用的<<运算符是一个具有多个重载的运算符。

Yes.


These operator functions are just ordinary functions with the special names operator@. There's no restriction that they cannot be overloaded. In fact, the << operator used by iostream is an operator with multiple overloads.

只等公子 2024-09-14 20:27:07

实现 operator+() 的规范形式是一个基于 operator+=() 的自由函数,当您拥有 + 时,您的用户会期望它。 += 更改其左侧参数,因此应该是成员。 + 对称地处理其参数,因此应该是一个自由函数。

像这样的事情应该做:(

//Beware, brain-compiled code ahead!
class MyClass {
public:
    MyClass& operator+=(const MyClass &rhs) const
    {
      // code for adding MyClass to MyClass
      return *this;
    }
    MyClass& operator+=(int rhs) const
    {
      // code for adding int to MyClass
      return *this;
    }
};


inline MyClass operator+(MyClass lhs, const MyClass& rhs) {
  lhs += rhs;
  return lhs;
}
inline MyClass operator+(MyClass lhs, int rhs) {
  lhs += rhs;
  return lhs;
}
// maybe you need this one, too
inline MyClass operator+(int lhs, const MyClass& rhs) {
  return rhs + lhs; // addition should be commutative
}

请注意,使用其类定义定义的成员函数是隐式内联。另请注意,在MyClass内,前缀MyClass:: 要么不需要,要么甚至是错误的。)

The canonical form of implementing operator+() is a free function based on operator+=(), which your users will expect when you have +. += changes its left-hand argument and should thus be a member. The + treats its arguments symmetrically, and should thus be a free function.

Something like this should do:

//Beware, brain-compiled code ahead!
class MyClass {
public:
    MyClass& operator+=(const MyClass &rhs) const
    {
      // code for adding MyClass to MyClass
      return *this;
    }
    MyClass& operator+=(int rhs) const
    {
      // code for adding int to MyClass
      return *this;
    }
};


inline MyClass operator+(MyClass lhs, const MyClass& rhs) {
  lhs += rhs;
  return lhs;
}
inline MyClass operator+(MyClass lhs, int rhs) {
  lhs += rhs;
  return lhs;
}
// maybe you need this one, too
inline MyClass operator+(int lhs, const MyClass& rhs) {
  return rhs + lhs; // addition should be commutative
}

(Note that member functions defined with their class' definition are implicitly inline. Also note, that within MyClass, the prefix MyClass:: is either not needed or even wrong.)

靖瑶 2024-09-14 20:27:07

是的,您可以像这样重载运算符。但我不确定你指的“开关盒”是什么。如果你有一个转换构造函数,你就可以接受一个重载,

class MyClass{
...
// code for creating a MyClass out of an int
MyClass(int n) { ... }
...
inline const MyClass MyClass::operator+(const MyClass &addend) const {
    cout<<"Adding MyClass+MyClass"<<endl;
    ...//Code for adding MyClass with MyClass
}
...
};

根本不需要任何开关。如果“MyClass”在逻辑上代表一个数字,则这是合格的。

请注意,您应该通过非成员函数重载这些运算符。在您的代码中 5 + c1 不起作用,因为没有运算符将 int 作为左侧。下面的代码可以工作

inline const MyClass operator+(const MyClass &lhs, const MyClass &rhs) {
  // ...
}

现在,如果保留转换构造函数,则可以以最小的代码开销在任一侧添加 int 。

Yes, you can overload operators like this. But I'm not sure what "switch case" you are referring to. You can live with one overload if you have a converting constructor

class MyClass{
...
// code for creating a MyClass out of an int
MyClass(int n) { ... }
...
inline const MyClass MyClass::operator+(const MyClass &addend) const {
    cout<<"Adding MyClass+MyClass"<<endl;
    ...//Code for adding MyClass with MyClass
}
...
};

No switch is needed at all. This is eligible if "MyClass" logically represents a number.

Notice that you should overload these operators by non-member functions. In your code 5 + c1 would not work, because there is no operator that takes an int as left hand side. The following would work

inline const MyClass operator+(const MyClass &lhs, const MyClass &rhs) {
  // ...
}

Now if you keep the converting constructor you can add the int by either side with minimal code overhead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文