在typedef结构中重载运算符(c ++)

tuk*_*ket 27 c++ struct typedef operator-keyword

我想创建一个名为pos(从位置)的typedef结构来存储坐标x和y.我试图为这个结构重载一些运算符,但它不编译.

typedef struct {
    int x;
    int y;

    inline pos operator=(pos a) {
        x=a.x;
        y=a.y;
        return a;
    }

    inline pos operator+(pos a) {
        return {a.x+x,a.y+y};
    }

    inline bool operator==(pos a) {
       if (a.x==x && a.y== y)
          return true;
       else
          return false;
    }
} pos;
Run Code Online (Sandbox Code Playgroud)

我也想知道这个之间的区别:

inline bool operator==(pos a) {
    if(a.x==x && a.y== y)
       return true;
      else
       return false;
}
Run Code Online (Sandbox Code Playgroud)

还有这个:

bool operator==(pos a) const {
      if(a.x==x && a.y== y)
         return true;
      else
         return false;
}
Run Code Online (Sandbox Code Playgroud)

Who*_*aig 67

您的声明及其成员的细分有点乱七八糟:

除掉 typedef

typedef既不是必需的,也不是C++中的类/结构声明所不需要的.您的成员不了解posas-written 声明,这是您当前编译失败的核心.

改变这个:

typedef struct {....} pos;
Run Code Online (Sandbox Code Playgroud)

对此:

struct pos { ... };
Run Code Online (Sandbox Code Playgroud)

删除无关的内联

您既可以在类定义中声明定义成员运算符.inline只要您的实现保留在其当前位置(类定义),就不需要该关键字


返回*this适当的引用

这与您实现中的大量复制结构有关,如果没有这么做的充分理由就不应该这样做.它与以下表达意识形态有关:

a = b = c;
Run Code Online (Sandbox Code Playgroud)

这将分配cb,然后将结果值b分配给a.这等同于以下代码,与您的想法相反:

a = c;
b = c;
Run Code Online (Sandbox Code Playgroud)

因此,您的赋值运算符应该如下实现:

pos& operator =(const pos& a)
{
    x = a.x;
    y = a.y;
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

即使在这里,也不需要这样做.默认的复制赋值运算符将为您免费执行上述操作(和代码!woot!)

注意:有时应避免使用上述内容,以支持复制/交换习惯用法.虽然这个特定情况不需要,但它可能如下所示:

pos& operator=(pos a) // by-value param invokes class copy-ctor
{
    this->swap(a);
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

然后实现交换方法:

void pos::swap(pos& obj)
{
    // TODO: swap object guts with obj
}
Run Code Online (Sandbox Code Playgroud)

这样做是为了利用类copy-ctor制作副本,然后利用异常安全交换来执行交换.结果是传入的副本会离开(并销毁)对象的旧内容,而您的对象则拥有对象的所有权.阅读更多复制/交换习语,以及其中的优点和缺点.


适当时通过const引用传递对象

您所有成员的所有输入参数当前都在复制调用时传递的内容.虽然对于像这样的代码来说可能是微不足道的,但对于较大的对象类型来说它可能非常昂贵.这里给出一个例子:

改变这个:

bool operator==(pos a) const{
    if(a.x==x && a.y== y)return true;
    else return false;
}
Run Code Online (Sandbox Code Playgroud)

对此:(也简化)

bool operator==(const pos& a) const
{
    return (x == a.x && y == a.y);
}
Run Code Online (Sandbox Code Playgroud)

没有拷贝任何由,从而产生更高效的代码.


最后,在回答你的问题时,成员函数或声明为的运算符const与不运行的运算符之间有什么区别?

const构件声明调用该成员将修改底层对象(可变声明不耐受).只能constconst对象或const引用和指针调用成员函数.例如,您operator +()不会修改本地对象,因此应声明为const.您operator =()清楚地修改了本地对象,因此操作员不应该这样const.


摘要

struct pos
{
    int x;
    int y;

    // default + parameterized constructor
    pos(int x=0, int y=0) 
        : x(x), y(y)
    {
    }

    // assignment operator modifies object, therefore non-const
    pos& operator=(const pos& a)
    {
        x=a.x;
        y=a.y;
        return *this;
    }

    // addop. doesn't modify object. therefore const.
    pos operator+(const pos& a) const
    {
        return pos(a.x+x, a.y+y);
    }

    // equality comparison. doesn't modify object. therefore const.
    bool operator==(const pos& a) const
    {
        return (x == a.x && y == a.y);
    }
};
Run Code Online (Sandbox Code Playgroud)

EDIT OP希望了解赋值运算符链的工作原理.以下演示了如何:

a = b = c;
Run Code Online (Sandbox Code Playgroud)

相当于:

b = c;
a = b;
Run Code Online (Sandbox Code Playgroud)

而且这并不总是等同于:

a = c;
b = c;
Run Code Online (Sandbox Code Playgroud)

示例代码:

#include <iostream>
#include <string>
using namespace std;

struct obj
{
    std::string name;
    int value;

    obj(const std::string& name, int value)
        : name(name), value(value)
    {
    }

    obj& operator =(const obj& o)
    {
        cout << name << " = " << o.name << endl;
        value = (o.value+1); // note: our value is one more than the rhs.
        return *this;
    }    
};

int main(int argc, char *argv[])
{

    obj a("a", 1), b("b", 2), c("c", 3);

    a = b = c;
    cout << "a.value = " << a.value << endl;
    cout << "b.value = " << b.value << endl;
    cout << "c.value = " << c.value << endl;

    a = c;
    b = c;
    cout << "a.value = " << a.value << endl;
    cout << "b.value = " << b.value << endl;
    cout << "c.value = " << c.value << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

产量

b = c
a = b
a.value = 5
b.value = 4
c.value = 3
a = c
b = c
a.value = 4
b.value = 4
c.value = 3
Run Code Online (Sandbox Code Playgroud)

  • @ user1754322查看(并尝试)我在本答案结尾处发布的样本. (2认同)

cdh*_*wie 6

而不是typedef struct { ... } pos;你应该做的struct pos { ... };.这里的问题是您pos在定义之前使用类型名称.通过将名称移动到结构定义的顶部,您可以在结构定义本身中使用该名称.

此外,该typedef struct { ... } name;模式是C-ism,并且在C++中没有多少位置.

要回答你的问题inline,这种情况没有区别.在struct/class定义中定义方法时,它是内联隐式声明的.当您明确指定时inline,编译器会有效地忽略它,因为该方法已经内联声明.

(inline如果在多个目标文件中定义了相同的方法,方法将不会触发链接器错误;链接器将简单地忽略除了其中一个之外的所有方法,假设它们都是相同的实现.这是内联方法中唯一保证的行为更改现在,它们不会影响编译器关于是否内联函数的决定;它们只是简化了所有翻译单元中的函数实现的可用性,这使得编译器可以选择内联函数,如果它决定它将是有益的这样做.)

  • 如果它们不是完全相同的实现,则它是未定义的行为. (2认同)

Kro*_*ark 5

尝试这个:

struct Pos{
    int x;
    int y;

    inline Pos& operator=(const Pos& other){
        x=other.x;
        y=other.y;
        return *this;
    }

    inline Pos operator+(const Pos& other) const {
        Pos res {x+other.x,y+other.y};
        return res;
    }

    const inline bool operator==(const Pos& other) const {
        return (x==other.x and y == other.y);
    }
 };  
Run Code Online (Sandbox Code Playgroud)