C++:重载数学运算符

Bru*_*dle 3 c++ operator-overloading

我正在寻找重载,比方说,添加运算符并让它添加两个相同类的对象.当我在头文件中的类声明中声明这个"operator +"原型函数时,我将两个对象作为参数传递.我得到一个编译器错误,说"二进制'运算符+'有太多的参数".我在网上搜索一个答案,发现在编译出来的头文件中声明了一个内联函数.我想知道我做错了什么,或者我在这里错过了什么.这是我在头文件中使用的代码.

class Person
{
private:
    int age;
    double weight;
public:
    Person::Person();                           //default constructor       
    Person::~Person();                           //default desctructor
    Person operator+(Person r, Person i);
};
Run Code Online (Sandbox Code Playgroud)

这编译了我上面提到的错误.下面是编译好的代码.

class Person
{
private:
    int age;
    double weight;
public:
    Person::Person();                           //default constructor       
    Person::~Person();                           //default desctructor
};
inline Person operator+(Person r, Person i)
{
return Person(0,0); 
}
Run Code Online (Sandbox Code Playgroud)

ags*_*mek 7

如果您声明oparator+为实例函数,则第一个参数将作为this对象传递,因此您只需要一个参数.阅读本文以获取更多信息,特别是尝试理解这个const概念:

http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html

参考文献中建议的最佳方法是:

class Person
{
    ...
    Person &operator+=(const Person &i);
    const Person operator+(const Person &i) const;
    ...
};

Person &Person::operator+=(const Person &i) {
    ...   // Do the compound assignment work.
    return *this;
}

const Person Person::operator+(const Person &i) const {    
    Person result = *this;     // Make a copy of myself.  Same as MyClass result(*this);
    result += i;            // Use += to add other to the copy.
    return result;              // All done!
}
Run Code Online (Sandbox Code Playgroud)

如果您决定使用const版本,请记住您只能调用const方法thisi引用.这是首选方式.

我引用的文章首先解释了重载的概念,+=然后更详细地定义了+使用+=.这是一个好主意,因为+=运算符必须单独过载.

此外 - DavidRodríguez建议operator+将其作为自由函数实现,而不管是否存在+ =.

  • -1来自我,因为不鼓励使用`const`.使用`const`是IMO,它是C++程序员工具箱中最强大的工具之一,同时也是一个你不太可能伤害自己的工具.这是该语言的最大特色之一,应尽可能鼓励使用它. (5认同)
  • 劝阻const /鼓励使用非const版本...这是一个可怕的建议.从语义上来说,"a + b"不应该既不修改"a"也不应修改"b",因此将它作为"const"最有意义.我发现你做的最后一次编辑很有意思(用`+ =`实现`+`,但仍然错过建议将`+`作为自由函数实现,无论是否存在`+ =`) (2认同)

sbi*_*sbi 6

每个成员函数都有一个隐含的第一个参数:this.对于运营商来说也是如此.因此,如果你想创建operator+()一个成员,它必须只接受一个参数,即右操作数,因为左操作数已经是this.

但是,对于可以是成员函数或自由函数的二元运算符,我的经验法则是使它们成为一个自由函数,对称地处理它们的参数(operator+()不改变它的任何一个操作数),并使它们成为一个成员函数哪些不(operator+=()改变其左操作数,但不改变其右侧).
此外,对于所有算术运算符,基于它们的组合赋值版本实现它们有一个很好的模式.也就是说,operator+()将基于operator+=(),-基于-=等等.
除此之外,您不希望不必要地复制类对象,但通常希望它们按const引用传递.

基于此,我的规范版本operator+将是:

class Person
{
public:
    Person& operator+=(const Person& i)
    {
      // whatever
      return *this;
    }
};

inline Person operator+(Person lhs, const Person& rhs)
{
  lhs += rhs; // note: lhs passed per copy
  return lhs;
}
Run Code Online (Sandbox Code Playgroud)

然而.关于运算符重载的最重要的经验法则可能是:不要这样做.这可能听起来有点荒谬,但最常见的命名功能比运营商要好得多,因为后者使代码更少比正常职能可读.在编写代码时,可读性应该是最重要的方面.除非运算符在应用程序域中具有明确且无可争议的含义,否则不要为类重载它.
在您的示例中,肯定没有干净且无可争议的运算符含义+适用于两个人.在现实世界中添加人物意味着什么?(我能想到的第一个意思就是不会有一个人,而是一群人.:))
因此,除非为你的Person班级重载这个操作员是一个家庭作业,我强烈建议反对它.(如果是作业,我会责怪老师发现这么糟糕的例子.)