我正在学习C ++,我创建了两个简单的hello-world应用程序。在他们两个中我使用运算符重载,但这是问题所在。在第一个,我可以为重载运算符提供两个参数,这很好。
标题
enum Element {a,b,c,d,e};
Element operator + (Element x, Element y);
//more overloads for -, *, / here
来源:
Element operator + (Element x, Element y) {
return ArrayOfElements[x][y];
}
但是在我的第二个应用程序(简单的复数计算器)中 - 这种方法不起作用。在谷歌搜索并弄清楚原因之后,我最终得到了这段代码:
标题
struct Complex {
double Re;
double Im;
Complex (double R, double I) : Re(R), Im(I) { }
Complex operator + (Complex &Number);
//more overloads
};
来源:
Complex Complex::operator + (Complex &Number)
{
Complex tmp = Complex(0, 0);
tmp.Re = Re + Number.Re;
tmp.Im = Im + Number.Im;
return tmp;
}
它现在正在运行,但我想知道,为什么在第一段代码中我被允许在operator
重载中放入两个参数,但是第二个我被赋予了以下错误?
complex.cpp:5:51: error: 'Complex Complex::operator+(Complex, Complex)' must take either zero or one argument
每当我使用课程时都是一样的。我一直在寻找许多文档,第二种方式似乎更正确。也许是因为不同的论证类型?
使用-Wall -pedantic
使用g++
参数编译的两个源都使用相同的库。
答案 0 :(得分:29)
假设你有一个这样的类:
class Element {
public:
Element(int value) : value(value) {}
int getValue() const { return value; }
private:
int value;
};
定义二元运算符有四种方法,例如+
。
作为免费功能,只能访问班级的public
成员:
// Left operand is 'a'; right is 'b'.
Element operator+(const Element& a, const Element& b) {
return Element(a.getValue() + b.getValue());
}
e1 + e2 == operator+(e1, e2)
作为会员功能,可以访问班级的所有成员:
class Element {
public:
// Left operand is 'this'; right is 'other'.
Element operator+(const Element& other) const {
return Element(value + other.value);
}
// ...
};
e1 + e2 == e1.operator+(e2)
作为friend
函数,可以访问该类的所有成员:
class Element {
public:
// Left operand is 'a'; right is 'b'.
friend Element operator+(const Element& a, const Element& b) {
return a.value + b.value;
}
// ...
};
e1 + e2 == operator+(e1, e2)
作为在类体外定义的friend
函数 - 与#3的行为相同:
class Element {
public:
friend Element operator+(const Element&, const Element&);
// ...
};
Element operator+(const Element& a, const Element& b) {
return a.value + b.value;
}
e1 + e2 == operator+(e1, e2)
答案 1 :(得分:4)
由于+是二元运算符,如果在结构/类中重载它,则只能提供一个操作数,原因是第一个操作数隐式地是调用对象。这就是为什么在第一种情况下,你有两个参数,因为它在你的类/结构的范围之外,而在第二种情况下,它被重载为成员函数。
答案 2 :(得分:3)
如果您希望operator+
将两个操作数作为显式参数,则必须将其定义为自由(即非成员)函数:
class Complex {
friend Complex operator+(const Complex& lhs, const Complex& rhs);
}
Complex operator+(const Complex& lhs, const Complex& rhs) {
...
}
如果左操作数是基本类型,或者是您不控制的类(因此无法添加成员函数),则 使用此表单。< / p>
答案 3 :(得分:1)
如果重载函数是类的成员函数,我们只传递一个参数,并且有一个隐藏参数( this 指针)指向执行二进制操作所需的其他对象,如& #39; +&#39 ;. 此指针指向其中一个操作数并调用重载函数;而其他操作数作为参数传递。 例如:
class ExampleClass
{
public:
int x;
//a this pointer will be passed to this function
ExampleClass& operator+(const ExampleClass& o){ return x+o.x; }
};
ExampleClass obj1, obj2, obj;
obj = obj1 + obj2; //the overloaded function is called as obj1.operator+(obj2) internally
//this pointer is passed to the function
当重载函数不是成员函数(自由函数或朋友函数)时,我们不会将 this 指针提供给重载函数。在这种情况下,编译器需要函数的两个参数作为操作数。
class ExampleClass
{
public:
int x;
//this pointer will not be passed to this function
friend ExampleClass& operator+(const ExampleClass& o1, const ExampleClass& o2){ return o1.x+o2.x; }
};
obj = obj1 + obj2; //the overloaded function is called as operator+(obj1, obj2) internally
答案 4 :(得分:0)
e1 + e2 == e1.operator +(e2)这意味着e1是一个对象,运算符+是一个成员而e2是一个变量.basicaly oops允许我们只写e1 + e2编译器自动理解为e1。操作者+(E1)