运算符重载如何工作,为什么它在我的情况下不起作用?
How does operator overloading work, and why doesn't it work in my case?
有人向我提供了一个驱动程序函数,该函数应该演示涉及复数的运算符重载的结果。在阅读了一段时间的重载之后,我设法以一种成功编译的方式编写了代码,但是在这个过程中的某个地方,程序没有输出正确的值。
据我了解,重载本质上就像一个函数。对象被传递,然后 "function" 可以用它做 arithmetic/whatever 和 return 一个新对象。不过,我有点迷失的地方是重载如何知道传递的是什么值。例如,在我的例子中,我重载了“+”和“=”运算符,以便以 "x = y + z" 的形式添加两个复数。当编译器遇到“=”符号时,我假设它只是传递左侧和右侧的任何内容并传递它们?与“+”相同。在这种情况下,它会传递 "y" 因为它是左边的对象,而 "z" 因为它是右边的对象?
这是我当前的 "complex" class,其中包括重载定义。
class Complex {
private:
double realPart;
double imaginaryPart;
public:
// friends
friend ostream & operator<<(ostream &out, const Complex &c);
friend istream & operator>>(istream &in, Complex &c);
// constructors
Complex()
{
realPart = 0;
imaginaryPart = 0;
}
Complex(double real)
{
realPart = real;
imaginaryPart = 0;
}
Complex(double real, double imaginary)
{
realPart = real;
imaginaryPart = imaginary;
}
// end of constructors
// + overloading
Complex operator+(Complex const &c)
{
Complex Add;
Add.realPart = realPart + c.realPart;
Add.imaginaryPart = imaginaryPart + c.imaginaryPart;
return Add;
}
// - overloading
Complex operator-(Complex const &c)
{
Complex Subtract;
Subtract.realPart = realPart - c.realPart;
Subtract.imaginaryPart = imaginaryPart - c.imaginaryPart;
return Subtract;
}
// * overloading
Complex operator*(Complex const &c)
{
Complex Multiply;
Multiply.realPart = (realPart * c.realPart) - (imaginaryPart * c.imaginaryPart);
Multiply.imaginaryPart = (realPart * c.imaginaryPart) - (imaginaryPart * c.realPart);
return Multiply;
}
// = overloading
Complex operator=(Complex const &c)
{
Complex Assignment;
Assignment.realPart = realPart;
Assignment.imaginaryPart = imaginaryPart;
return Assignment;
}
// == overloading
bool operator==(Complex const &c)
{
Complex Compare;
if (Compare.realPart == realPart && Compare.imaginaryPart == imaginaryPart)
{
return true;
}
else
{
return false;
}
}
// != overloading
bool operator!=(Complex const &c)
{
Complex NotEqual;
if (NotEqual.realPart == realPart && NotEqual.imaginaryPart == imaginaryPart)
{
return false;
}
else
{
return true;
}
}
};
// << overloading
ostream& operator<<(ostream& out, const Complex &c)
{
out << c.realPart;
if (c.imaginaryPart >= 0)
{
out << " + " << c.imaginaryPart << "i" << endl;
}
else
{
out << " - " << fabs (c.imaginaryPart) << "i" << endl;
}
return out;
}
// >> overloading
istream& operator>>(istream &in, Complex &c)
{
in >> c.realPart;
in >> c.imaginaryPart;
return in;
}
这是驱动程序:
int main()
{
for (double i = 1; i < 10; ++ i)
{
Complex y{i * 2.7, i + 3.2};
Complex z{i * 6, i + 8.3};
Complex x;
Complex k;
std::cout << "Enter a complex number in the form: (a, b)\n? ";
std::cin >> k; // demonstrating overloaded >>
std::cout << "x: " << x << "\ny: " << y << "\nz: " << z << "\nk: " << k << '\n'; // demonstrating overloaded <<
x = y + z; // demonstrating overloaded + and =
std::cout << "\nx = y + z:\n" << x << " = " << y << " + " << z << '\n';
x = y - z; // demonstrating overloaded - and =
std::cout << "\nx = y - z:\n" << x << " = " << y << " - " << z << '\n';
x = y * z; // demonstrating overloaded * and =
std::cout << "\nx = y * z:\n" << x << " = " << y << " * " << z << "\n\n";
if (x != k)
{ // demonstrating overloaded !=
std::cout << x << " != " << k << '\n';
}
std::cout << '\n';
x = k;
if (x == k)
{
// demonstrating overloaded ==
std::cout << x << " == " << k << '\n';
}
std::cout << std::endl;
}
}
在 运行 上,问题似乎出在对象 "x" 上。输入“5 2”仍会输出 "x: 0 + 0i" 这使我相信问题出在“=”或流运算符的重载上。也就是说,我不太明白为什么什么都没有发生。
我构建“=”重载定义的方式是否如我所想的有误,还是我遗漏了更大的东西?
你的=
错了;它应该 return *this
。
Complex& operator=(Complex const &c)
{
realPart = c.realPart;
imaginaryPart = c.imaginaryPart;
return *this;
}
解决这个问题,其余大部分看起来都很正常。
operator=()
不正确:用户 Yakk - Adam
已经向您展示了如何修复它。让您深入了解为什么它是错误的以及 return *this
做了什么;让我们看看您的原始功能:
Complex operator=(Complex const &c) {
Complex Assignment;
Assignment.realPart = realPart;
Assignment.imaginaryPart = imaginaryPart;
return Assignment;
}
此处您的签名采用对另一个 Complex
对象的 const 引用这部分是正确的。您的 return 类型是 Complex
对象,这本质上是错误的,因为您不想 return 对象的副本。这里的objective是进行赋值的。这意味着您必须对原始 LHS
实例进行更改。
在表达式中A = B + C
; A
被认为是 LHS
实例。在这里,您要为表达式 (B + C)
赋值,它们都是 RHS
值。
因此,当 Yakk - Adam
向您展示了如何解决此问题时:
Complex& operator=(Complex const &c) {
realPart = c.realPart;
imaginaryPart = c.imaginaryPart;
return *this;
}
其中一个区别是 return 类型现在是特定对象的 Reference
而不是对象的副本。
另一个区别是不需要像在原始版本中那样创建本地临时副本:
Complex Assignment; // this is not needed
通过从 operator=()
中删除它,他只需替换这些代码行:
// Assignment.realPart = realPart; // To
realPart = c.realPart;
// Assignment.imaginaryPart = imaginaryPart; // To
imaginaryPart = c.imaginaryPart;
此处您直接使用 class 的成员并为它们分配属于另一个或传递给运算符的 c
的值。
最后 return 您的 LHS
实例更新后的值;这是您必须 return 取消引用 this 指针的地方。
*this
是什么意思? this指针是属于所有class
和struct
类型的特殊指针。例如,任何时候你有 class 对象:
class Foo {
public:
int bar { 10 };
void addFive();
};
您可以直接在您的成员函数中使用 this 指针:
void Foo::addFive() {
this->bar += 5; // same as below (this) belongs to this particular instance.
// bar += 5;
}
关于你的operator=()
;因为你是 returnreference
,你不能简单地 return this
。这将 return this
指针。我们不需要指向对象的指针,因为我们需要对对象的引用;所以我们必须通过 returning *this
来引用 this
指针。
我希望这能帮助您解决问题。
有人向我提供了一个驱动程序函数,该函数应该演示涉及复数的运算符重载的结果。在阅读了一段时间的重载之后,我设法以一种成功编译的方式编写了代码,但是在这个过程中的某个地方,程序没有输出正确的值。
据我了解,重载本质上就像一个函数。对象被传递,然后 "function" 可以用它做 arithmetic/whatever 和 return 一个新对象。不过,我有点迷失的地方是重载如何知道传递的是什么值。例如,在我的例子中,我重载了“+”和“=”运算符,以便以 "x = y + z" 的形式添加两个复数。当编译器遇到“=”符号时,我假设它只是传递左侧和右侧的任何内容并传递它们?与“+”相同。在这种情况下,它会传递 "y" 因为它是左边的对象,而 "z" 因为它是右边的对象?
这是我当前的 "complex" class,其中包括重载定义。
class Complex {
private:
double realPart;
double imaginaryPart;
public:
// friends
friend ostream & operator<<(ostream &out, const Complex &c);
friend istream & operator>>(istream &in, Complex &c);
// constructors
Complex()
{
realPart = 0;
imaginaryPart = 0;
}
Complex(double real)
{
realPart = real;
imaginaryPart = 0;
}
Complex(double real, double imaginary)
{
realPart = real;
imaginaryPart = imaginary;
}
// end of constructors
// + overloading
Complex operator+(Complex const &c)
{
Complex Add;
Add.realPart = realPart + c.realPart;
Add.imaginaryPart = imaginaryPart + c.imaginaryPart;
return Add;
}
// - overloading
Complex operator-(Complex const &c)
{
Complex Subtract;
Subtract.realPart = realPart - c.realPart;
Subtract.imaginaryPart = imaginaryPart - c.imaginaryPart;
return Subtract;
}
// * overloading
Complex operator*(Complex const &c)
{
Complex Multiply;
Multiply.realPart = (realPart * c.realPart) - (imaginaryPart * c.imaginaryPart);
Multiply.imaginaryPart = (realPart * c.imaginaryPart) - (imaginaryPart * c.realPart);
return Multiply;
}
// = overloading
Complex operator=(Complex const &c)
{
Complex Assignment;
Assignment.realPart = realPart;
Assignment.imaginaryPart = imaginaryPart;
return Assignment;
}
// == overloading
bool operator==(Complex const &c)
{
Complex Compare;
if (Compare.realPart == realPart && Compare.imaginaryPart == imaginaryPart)
{
return true;
}
else
{
return false;
}
}
// != overloading
bool operator!=(Complex const &c)
{
Complex NotEqual;
if (NotEqual.realPart == realPart && NotEqual.imaginaryPart == imaginaryPart)
{
return false;
}
else
{
return true;
}
}
};
// << overloading
ostream& operator<<(ostream& out, const Complex &c)
{
out << c.realPart;
if (c.imaginaryPart >= 0)
{
out << " + " << c.imaginaryPart << "i" << endl;
}
else
{
out << " - " << fabs (c.imaginaryPart) << "i" << endl;
}
return out;
}
// >> overloading
istream& operator>>(istream &in, Complex &c)
{
in >> c.realPart;
in >> c.imaginaryPart;
return in;
}
这是驱动程序:
int main()
{
for (double i = 1; i < 10; ++ i)
{
Complex y{i * 2.7, i + 3.2};
Complex z{i * 6, i + 8.3};
Complex x;
Complex k;
std::cout << "Enter a complex number in the form: (a, b)\n? ";
std::cin >> k; // demonstrating overloaded >>
std::cout << "x: " << x << "\ny: " << y << "\nz: " << z << "\nk: " << k << '\n'; // demonstrating overloaded <<
x = y + z; // demonstrating overloaded + and =
std::cout << "\nx = y + z:\n" << x << " = " << y << " + " << z << '\n';
x = y - z; // demonstrating overloaded - and =
std::cout << "\nx = y - z:\n" << x << " = " << y << " - " << z << '\n';
x = y * z; // demonstrating overloaded * and =
std::cout << "\nx = y * z:\n" << x << " = " << y << " * " << z << "\n\n";
if (x != k)
{ // demonstrating overloaded !=
std::cout << x << " != " << k << '\n';
}
std::cout << '\n';
x = k;
if (x == k)
{
// demonstrating overloaded ==
std::cout << x << " == " << k << '\n';
}
std::cout << std::endl;
}
}
在 运行 上,问题似乎出在对象 "x" 上。输入“5 2”仍会输出 "x: 0 + 0i" 这使我相信问题出在“=”或流运算符的重载上。也就是说,我不太明白为什么什么都没有发生。
我构建“=”重载定义的方式是否如我所想的有误,还是我遗漏了更大的东西?
你的=
错了;它应该 return *this
。
Complex& operator=(Complex const &c)
{
realPart = c.realPart;
imaginaryPart = c.imaginaryPart;
return *this;
}
解决这个问题,其余大部分看起来都很正常。
operator=()
不正确:用户 Yakk - Adam
已经向您展示了如何修复它。让您深入了解为什么它是错误的以及 return *this
做了什么;让我们看看您的原始功能:
Complex operator=(Complex const &c) { Complex Assignment; Assignment.realPart = realPart; Assignment.imaginaryPart = imaginaryPart; return Assignment; }
此处您的签名采用对另一个 Complex
对象的 const 引用这部分是正确的。您的 return 类型是 Complex
对象,这本质上是错误的,因为您不想 return 对象的副本。这里的objective是进行赋值的。这意味着您必须对原始 LHS
实例进行更改。
在表达式中A = B + C
; A
被认为是 LHS
实例。在这里,您要为表达式 (B + C)
赋值,它们都是 RHS
值。
因此,当 Yakk - Adam
向您展示了如何解决此问题时:
Complex& operator=(Complex const &c) { realPart = c.realPart; imaginaryPart = c.imaginaryPart; return *this; }
其中一个区别是 return 类型现在是特定对象的 Reference
而不是对象的副本。
另一个区别是不需要像在原始版本中那样创建本地临时副本:
Complex Assignment; // this is not needed
通过从 operator=()
中删除它,他只需替换这些代码行:
// Assignment.realPart = realPart; // To realPart = c.realPart; // Assignment.imaginaryPart = imaginaryPart; // To imaginaryPart = c.imaginaryPart;
此处您直接使用 class 的成员并为它们分配属于另一个或传递给运算符的 c
的值。
最后 return 您的 LHS
实例更新后的值;这是您必须 return 取消引用 this 指针的地方。
*this
是什么意思? this指针是属于所有class
和struct
类型的特殊指针。例如,任何时候你有 class 对象:
class Foo {
public:
int bar { 10 };
void addFive();
};
您可以直接在您的成员函数中使用 this 指针:
void Foo::addFive() {
this->bar += 5; // same as below (this) belongs to this particular instance.
// bar += 5;
}
关于你的operator=()
;因为你是 returnreference
,你不能简单地 return this
。这将 return this
指针。我们不需要指向对象的指针,因为我们需要对对象的引用;所以我们必须通过 returning *this
来引用 this
指针。
我希望这能帮助您解决问题。