[Effective C++]条款24:若所有参数皆需类型转换,请为此采用non-menber函数
.
1、操作符重载&隐式类型转换
- C++中,操作符重载可以通过成员函数或非成员函数来实现。当操作符重载是成员函数时,左操作数必须是该类的对象。如果左操作数不是该类的对象,而是需要进行隐式转换的类型,编译器将无法找到匹配的成员函数,从而导致编译错误。
- 为了避免这个问题,可以将操作符重载定义为非成员函数。非成员函数允许左操作数和右操作数都进行隐式类型转换,从而解决编译错误的问题。
2、代码示例
- 创建一个Rational类,希望支持Rational对象与整数之间的加法操作。如果将加法操作符重载成成员函数,那么当整数作为左操作数时,编译器无法找到匹配的成员函数,导致编译失败
- 下面代码中2不是Rational对象,无法调用Rational的成员函数operator+,因为编译器不会对左操作数进行隐式类型转换,成员函数的调用依赖于类的实例。
class Rational {
public:
Rational(int numerator = 0, int denominator = 1)
: numerator_(numerator), denominator_(denominator) {}
// 成员函数重载加法操作符
Rational operator+(const Rational& other) const {
return Rational(numerator_ * other.denominator_ + other.numerator_ * denominator_,
denominator_ * other.denominator_);
}
private:
int numerator_;
int denominator_;
};
int main() {
Rational r1(1, 2);
Rational r2 = r1 + 2; // 正确:2 可以隐式转换为 Rational 对象
Rational r3 = 2 + r1; // 错误:2 不能作为左操作数调用成员函数 operator+
}
3、非成员函数重载
- 非成员函数,允许左操作数和右操作数都进行隐式类型转换
class Rational {
public:
Rational(int numerator = 0, int denominator = 1)
: numerator_(numerator), denominator_(denominator) {}
int numerator() const { return numerator_; }
int denominator() const { return denominator_; }
private:
int numerator_;
int denominator_;
};
// 非成员函数重载加法操作符
Rational operator+(const Rational& lhs, const Rational& rhs) {
return Rational(lhs.numerator() * rhs.denominator() + rhs.numerator() * lhs.denominator(),
lhs.denominator() * rhs.denominator());
}
int main() {
Rational r1(1, 2);
Rational r2 = r1 + 2; // 正确:2 可以隐式转换为 Rational 对象
Rational r3 = 2 + r1; // 正确:2 可以隐式转换为 Rational 对象
}
思维导图笔记: