一、转换函数 Conversion Functions(operators)
在 C++ 中,使用类作为具体类型,对现实世界对象进行抽象。有时,需要隐式地将一种具体类型转换为另一种具体类型或 C++ 内建数据类型。转换函数在这种情况下发挥着重要作用。它类似于类中的运算符重载函数。
转换函数写法:operator typeName();
- 转换函数必须是类的成员函数
- 转换函数不能指定返回值类型
- 转换函数不能有形参
例如下面的类:
class Fraction
{
public:
Fraction(int numerator, int denominator = 1)
:m_numerator(numerator), m_denominator(denominator)
{
}
//转换函数
operator double() const
{
return (double)m_numerator / m_denominator;
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
int main()
{
Fraction f(8,5);
double d = 4 + f;
cout << d << endl;
return 0;
}
输出:
5.6
注意: 编译器将在基于类型调用适当的功能时具有更多控制,而不是我们所期望的。所以使用类或对象的特定成员函数来执行此类转换才是良好的习惯。
二、构造函数隐式转换 non-explicit-one-argument constructor
class Fraction
{
public:
Fraction(int numerator, int denominator = 1)
:m_numerator(numerator), m_denominator(denominator)
{
}
Fraction operator + (const Fraction& f) {
return Fraction(m_numerator * f.m_denominator + f.m_numerator * m_denominator, m_denominator * f.m_denominator);
}
//转换函数
operator string() const
{
return to_string(m_numerator) + "/" + to_string(m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
int main()
{
Fraction f(8,5);
Fraction ff = f + 4; // 调用构造函数,将 4 转换成 Fraction(4, 1),然后再调用 operator +
cout << (string)ff << endl;
return 0;
}
输出:
28/5
三、转换函数与构造函数隐式转换(ambiguous)
class Fraction
{
public:
Fraction(int numerator, int denominator = 1)
:m_numerator(numerator), m_denominator(denominator)
{
}
Fraction operator + (const Fraction& f) {
return Fraction(m_numerator * f.m_denominator + f.m_numerator * m_denominator, m_denominator * f.m_denominator);
}
//转换函数
operator double() const
{
return (double)m_numerator / m_denominator;
}
operator string() const
{
return to_string(m_numerator) + "/" + to_string(m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
int main()
{
Fraction f(8,5);
Fraction ff = f + 4; // error: ambiguous overload for ‘operator+’ (operand types are ‘Fraction’ and ‘int’)
cout << ff << endl;
return 0;
}
输出:
main.cpp:54:21: error: ambiguous overload for ‘operator+’ (operand types are ‘Fraction’ and ‘int’)
54 | Fraction ff = f + 4;
| ~ ^ ~
| | |
| | int
| Fraction
main.cpp:54:21: note: candidate: ‘operator+(double, int)’
54 | Fraction ff = f + 4;
| ~~^~~
main.cpp:21:14: note: candidate: ‘Fraction Fraction::operator+(const Fraction&)’
21 | Fraction operator + (const Fraction& f) {
| ^~~~~~~~
- 可以将 4 隐式的转换为 Fraction 对象,然后调用 + 操作符重载
- 也可以将 f 转换为 double,再与 4 相加,最后再将 double 隐式转换为 Fraction 对象
四、禁止构造函数隐式转换
class Fraction
{
public:
explicit Fraction(int numerator, int denominator = 1)
:m_numerator(numerator), m_denominator(denominator)
{
}
Fraction operator + (const Fraction& f) {
return Fraction(m_numerator * f.m_denominator + f.m_numerator * m_denominator, m_denominator * f.m_denominator);
}
//转换函数
operator string() const
{
return to_string(m_numerator) + "/" + to_string(m_denominator);
}
operator double() const
{
return (double)m_numerator / m_denominator;
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
int main()
{
Fraction f(8,5);
// Fraction ff = f + 4; // error: conversion from ‘double’ to non-scalar type ‘Fraction’ requested
double ff = f + 4; // OK 5.6
cout << ff << endl;
return 0;
}
- 由于在构造函数前面增加了
explicit
关键字,所以不能将 4 转换成 Fraction 类型; - 也不能先将 f 转换成 double 类型,与 4 相加,再将 double 隐式转换成 Fraction 类型,所以会报错。
参考: