对于也重载了强制转换运算符的类型的类数学运算重载

1 c++ casting overloading class

作为我的大学任务的一部分,我需要为有理数编写类,覆盖数学运算符,比较运算符等。但我还需要重载强制转换为short,intlong类型。这是我的班级的简化代码:

\n
class RationalNumber {\n  long long numerator, divider;\npublic:\n  RationalNumber() : numerator(0), divider(1) {}\n  RationalNumber(long long numerator, long long divider = 1) : numerator(numerator), divider(divider) {}\n  \n  // Let\'s take only one math operator\n  RationalNumber operator*(const RationalNumber& other) {\n    return { numerator * other.numerator, divider * other.divider };\n  }\n\n  // And one cast operator\n  operator int() {\n    return numerator / divider;\n  }\n  //...\n};\n
Run Code Online (Sandbox Code Playgroud)\n

问题是,如果我现在想将 RationalNumber 对象乘以int,我会收到一条错误消息,指出此操作不明确:

\n
int main() {\n  int integer = 2;\n  RationalNumber rational(1, 2);\n  \n  rational * integer;\n  // Well, ambiguous:\n  // 1. Cast \'rational\' to int and multiply. Or\n  // 2. Cast \'integer\' to RationalNumber and RationalNumber::operator*\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

专门为单个添加构造函数int是行不通的。有效的方法是添加RationalNumber::operator*(int). 这种方法的问题是:我需要重写所有数学运算、比较运算等,因为int我已将运算符强制转换为 int -- operator int

\n

好的,但即使我会这样做,我第二次尝试使用unsigned编译器时也会收到大量关于转换和潜在数据丢失的警告unsignedint以为它会编译):

\n
class RationalNumber {\n  //...\npublic:\n  //...\n  RationalNumber operator*(int othNum) {\n    return { numerator * othNum, divider };\n  }\n  //...\n};\n\nint main() {\n  unsigned int uinteger = 2;\n  RationalNumber rational(1, 2);\n\n  rational * uinteger; // Well... AAAAAAA\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n
test.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\ntest.cpp:29:14: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:\n   29 |   rational * integer;\n      |              ^~~~~~~\ntest.cpp:14:18: note: candidate 1: \xe2\x80\x98RationalNumber RationalNumber::operator*(int)\xe2\x80\x99\n   14 |   RationalNumber operator*(int othNum) {\n      |                  ^~~~~~~~\ntest.cpp:29:14: note: candidate 2: \xe2\x80\x98operator*(int, unsigned int)\xe2\x80\x99 (built-in)\n   29 |   rational * integer;\n      | \n
Run Code Online (Sandbox Code Playgroud)\n

为了完全满足编译器的要求,我需要添加RationalNumber::operator*(unsigned). 现在让我们记住,我需要重载 3 个转换运算符和十几个数学/比较运算符。这意味着我需要为每个运算符重载创建 6 个额外函数。

\n

那么,我可以以某种方式强制编译器始终将值转换为有利于我的类吗?

\n

for*_*818 5

隐式转换可能会导致问题,并对可读性产生负面影响。如果可能,当您确定隐式转换合适时,请进行显式转换并在特殊情况下保留隐式转换。如果进行转换,调用就不再含糊不清explicit

explicit operator int() {
  return numerator / divider;
}
Run Code Online (Sandbox Code Playgroud)

现场演示

这是 C++ 默认值有点奇怪的众多情况之一。默认情况下,转换应该是显式的,只有在特殊情况下才可以是隐式的。