条款24:当一个类需要类型转换时,应使用 non-member 函数

例如:一个有理数类,想支持诸如加法、乘法等,是使用member 函数,还是使用 non-member 函数,还是使用 friend non-member 函数呢?


1,使用成员函数(member function)时

#include <iostream>
using namespace std;

class Rational {
public:
Rational(int num = 0, int den = 1) : numerator(num), denominator(den) {}

// member function
const Rational operator*(const Rational& rhs) const {
return Rational(numerator * rhs.numerator, denominator * rhs.denominator);
}

void print() const{
cout << numerator << "/" << denominator << endl;
}

int getNum() const { return numerator; }
int getDen() const { return denominator; }
private:
int numerator;
int denominator;

};

int main()
{
Rational oe(1, 8);
Rational oh(1, 2);

// success
Rational result = oe * oh;
result.print(); // (1,8) * (1,2) = (1, 16)


// success
result = oe * 2;
result.print(); // (1,8) * (2,1) = (2, 8)
// 这里2 进行了隐性转换
// Rational temp(2);>> temp(2,1)
// result = oe * temp;

// error
// result = 2 * oe;
// error C2677: 二进制“*”: 没有找到接受“Rational”类型的全局运算符(或没有可接受的转换)

system("pause");
return 0;
}

// output
1/16
2/8

2,使用非成员函数(non-member function)时

#include <iostream>
using namespace std;

class Rational {
public:
Rational(int num = 0, int den = 1) : numerator(num), denominator(den) {}

void print() const{
cout << numerator << "/" << denominator << endl;
}

int getNum() const { return numerator; }
int getDen() const { return denominator; }
private:
int numerator;
int denominator;

};

// non-member function
const Rational operator*(const Rational& lhs, const Rational& rhs) {
return Rational(lhs.getNum() * rhs.getNum(), lhs.getDen() * rhs.getDen());
}

int main()
{
Rational oe(1, 8);
Rational oh(1, 2);

// success
Rational result = oe * oh;
result.print(); // (1,8) * (1,2) = (1, 16)

// success
result = oe * 2;
result.print(); // (1,8) * (2,1) = (2, 8)
// 这里2 进行了隐性转换
// Rational temp(2);>> temp(2,1)
// result = oe * temp;

// success
result = 2 * oe;
result.print(); // (2,1) * (1,8) = (2, 8)
// 这里2 进行了隐性转换
// Rational temp(2);>> temp(2,1)
// result = temp * oe;

system("pause");
return 0;
}

// output
1/16
2/8
2/8

3,友元

本例而言是否定的,


结论:

只有当参数被列于参数列内(parameter list)时,参数才会是隐式类型转换的合格参与者。
​​​如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那个这个函数必须是个non-member​