你能避免数学运算符的多个运算符重载吗?
Can you Avoid Multiple Operator Overloads for Mathematical Operators?
假设我有一个非常简单的 Rational class,如下所示:
class Rational
{
int numer;
int denom;
public:
Rational(const int& numer, const int& denom) : numer(numer), denom(denom) {}
void operator*(const Rational& other) { std::cout << "multiply, simple as\n"; }
}
一切都很好。然后说我希望能够将我的 Rational class 乘以一个整数,所以我在 class:
中添加了另一个函数
class Rational
{
int numer;
int denom;
public:
Rational(const int& numer, const int& denom) : numer(numer), denom(denom) {}
void operator*(const Rational& other) { std::cout << "multiply, simple as\n"; }
void operator*(const int& other) { std::cout << "some math here\n"; }
}
好的,没什么大不了的。除了我实际上不能执行以下操作,因为参数的顺序都是错误的:
Rational mine(1, 2);
const Rational result = 2 * mine;
好的,再进行一次迭代,我得到以下结果:
class Rational
{
int numer;
int denom;
public:
Rational(const int& numer, const int& denom) : numer(numer), denom(denom) {}
void operator*(const Rational& other) { std::cout << "multiply, simple as\n"; }
void operator*(const int& other) { std::cout << "some math here\n"; }
friend void operator*(const int& other, const Rational& mine) { std::cout << "even more math here\n"; }
}
我想知道的是,是否有一种方法可以避免为我希望 class 支持的每个数学运算编写相同的函数两次,这样就可以了我可以按我想要的任何顺序用参数调用它。这很可能就是您必须在 C++ 的类型系统中实现此类事情的方式,但是必须为您希望 class 支持的每个数学运算添加此样板似乎有点烦人。
单一函数的问题在于 *
左右操作数的类型会有所不同(您必须以不同的方式使用它们)。
这可以通过将两个参数类型固定为 Rational
并创建从 int
x
到 Rational
x/1
的隐式转换来解决(无论如何这可能是可取的)。这样,在 2 * mine
中,2
将隐式转换为 Rational(2, 1) * mine
.
这是一个例子:
class Rational
{
int numer;
int denom;
public:
// default argument of denom=1 allows implicit conversion from int
Rational(int numer, int denom = 1) : numer(numer), denom(denom) {}
friend Rational operator*(const Rational& l, const Rational& r) {
std::cout << "Rational(" << l.numer << ", " << l.denom
<< ") * Rational(" << r.numer << ", " << r.denom << ")\n";
// calculate and return result
}
friend Rational operator/(const Rational& l, const Rational& r) { /* ... */ }
friend bool operator==(const Rational& l, const Rational& r) { /* ... */ }
};
假设我有一个非常简单的 Rational class,如下所示:
class Rational
{
int numer;
int denom;
public:
Rational(const int& numer, const int& denom) : numer(numer), denom(denom) {}
void operator*(const Rational& other) { std::cout << "multiply, simple as\n"; }
}
一切都很好。然后说我希望能够将我的 Rational class 乘以一个整数,所以我在 class:
中添加了另一个函数class Rational
{
int numer;
int denom;
public:
Rational(const int& numer, const int& denom) : numer(numer), denom(denom) {}
void operator*(const Rational& other) { std::cout << "multiply, simple as\n"; }
void operator*(const int& other) { std::cout << "some math here\n"; }
}
好的,没什么大不了的。除了我实际上不能执行以下操作,因为参数的顺序都是错误的:
Rational mine(1, 2);
const Rational result = 2 * mine;
好的,再进行一次迭代,我得到以下结果:
class Rational
{
int numer;
int denom;
public:
Rational(const int& numer, const int& denom) : numer(numer), denom(denom) {}
void operator*(const Rational& other) { std::cout << "multiply, simple as\n"; }
void operator*(const int& other) { std::cout << "some math here\n"; }
friend void operator*(const int& other, const Rational& mine) { std::cout << "even more math here\n"; }
}
我想知道的是,是否有一种方法可以避免为我希望 class 支持的每个数学运算编写相同的函数两次,这样就可以了我可以按我想要的任何顺序用参数调用它。这很可能就是您必须在 C++ 的类型系统中实现此类事情的方式,但是必须为您希望 class 支持的每个数学运算添加此样板似乎有点烦人。
单一函数的问题在于 *
左右操作数的类型会有所不同(您必须以不同的方式使用它们)。
这可以通过将两个参数类型固定为 Rational
并创建从 int
x
到 Rational
x/1
的隐式转换来解决(无论如何这可能是可取的)。这样,在 2 * mine
中,2
将隐式转换为 Rational(2, 1) * mine
.
这是一个例子:
class Rational
{
int numer;
int denom;
public:
// default argument of denom=1 allows implicit conversion from int
Rational(int numer, int denom = 1) : numer(numer), denom(denom) {}
friend Rational operator*(const Rational& l, const Rational& r) {
std::cout << "Rational(" << l.numer << ", " << l.denom
<< ") * Rational(" << r.numer << ", " << r.denom << ")\n";
// calculate and return result
}
friend Rational operator/(const Rational& l, const Rational& r) { /* ... */ }
friend bool operator==(const Rational& l, const Rational& r) { /* ... */ }
};