C++17模板类二元运算符双向重载编译报错问题排查
解决C++17模板类二元运算符双向重载编译错误
错误原因
成员函数形式的operator+只能定义1个参数——因为成员函数默认把类实例作为左操作数(通过this指针),你改成双参数的成员函数后,编译器无法将其识别为合法的二元运算符重载,自然会报"invalid operands"错误。
正确实现方案
要同时支持对象+值和值+对象,需要结合成员函数和非成员函数两种重载方式:
1. 成员函数实现对象+值
成员函数版的operator+接收右操作数(比如int),返回新的类实例:
template<typename T> class MyClass1 { private: T data; public: // 构造函数 MyClass1(T val) : data(val) {} // 成员函数:支持 MyClass1 + 值 MyClass1 operator+(const T& rhs) const { return MyClass1(data + rhs); } };
2. 非成员函数实现值+对象
非成员函数(可以是全局函数,或者类内声明的友元)接收左操作数(比如int)和右操作数(MyClass1实例),返回新的类实例:
// 全局非成员函数:支持 值 + MyClass1 template<typename T> MyClass1<T> operator+(const T& lhs, const MyClass1<T>& rhs) { return MyClass1<T>(lhs + rhs.data); }
如果需要访问类的私有成员,把这个函数声明为类的友元:
template<typename T> class MyClass1 { // ... 其他成员 ... // 声明友元,注意模板参数的写法 friend MyClass1<T> operator+<>(const T& lhs, const MyClass1<T>& rhs); }; // 友元函数的定义(和上面全局函数一致) template<typename T> MyClass1<T> operator+(const T& lhs, const MyClass1<T>& rhs) { return MyClass1<T>(lhs + rhs.data); }
完整测试代码
#include <iostream> template<typename T> class MyClass1 { private: T data; public: MyClass1(T val) : data(val) {} // 对象+值 MyClass1 operator+(const T& rhs) const { return MyClass1(data + rhs); } // 声明友元以支持值+对象 friend MyClass1<T> operator+<>(const T& lhs, const MyClass1<T>& rhs); // 用于打印测试 void print() const { std::cout << data << std::endl; } }; // 值+对象的实现 template<typename T> MyClass1<T> operator+(const T& lhs, const MyClass1<T>& rhs) { return MyClass1<T>(lhs + rhs.data); } int main() { MyClass1<int> temp(5); temp = temp + 1; // 对象+值,正常编译 temp.print(); // 输出6 temp = 2 + temp; // 值+对象,正常编译 temp.print(); // 输出8 return 0; }
额外说明
- C++17支持模板参数推导,所以返回
MyClass1(data + rhs)时不需要显式写MyClass1<T>(不过显式写也没问题)。 - 如果你想实现
+=这类复合赋值运算符,建议用成员函数实现,因为复合赋值会修改左操作数,成员函数更符合语义。
内容的提问来源于stack exchange,提问作者user18184114
相关产品推荐
相关产品推荐

