42

我想创建一个名为pos(从位置)存储坐标 x 和 y 的 typedef 结构。我正在尝试为此结构重载一些运算符,但它无法编译。

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;

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

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

和这个:

bool operator==(pos a) const {
      if(a.x==x && a.y== y)
         return true;
      else
         return false;
}
4

4 回答 4

94

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

去除typedef

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

改变这个:

typedef struct {....} pos;

对此:

struct pos { ... };

删除多余的内联

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


*this在适当的地方返回引用

这与您的实现中的大量复制构造有关,如果没有充分的理由,则不应这样做。它与以下的表达思想有关:

a = b = c;

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

a = c;
b = c;

因此,您的赋值运算符应该这样实现:

pos& operator =(const pos& a)
{
    x = a.x;
    y = a.y;
    return *this;
}

即使在这里,也不需要这样做。默认的复制分配操作员将免费为您执行上述操作(和代码!哇!)

注意:有时应避免上述情况以支持复制/交换习语。虽然在这种特定情况下不需要,但它可能看起来像这样:

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

然后实现一个swap方法:

void pos::swap(pos& obj)
{
    // TODO: swap object guts with obj
}

您这样做是为了利用类 copy-ctor 进行复制,然后利用异常安全交换来执行交换。结果是传入的副本离开(并破坏)了您的对象的旧内脏,而您的对象承担了那里的所有权。在此处阅读更多复制/交换习语,以及其中的优缺点。


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

您对所有成员的所有输入参数当前正在复制调用时传递的任何内容。虽然这样的代码可能很简单,但对于较大的对象类型来说可能非常昂贵。这里给出一个例子:

改变这个:

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

对此:(也简化了)

bool operator==(const pos& a) const
{
    return (x == a.x && y == a.y);
}

不会复制任何内容,从而产生更高效的代码。


最后,在回答您的问题时,声明为的成员函数或运算符与未声明的成员函数或运算符有什么区别const

const成员声明调用该成员不会修改底层对象(不支持可变声明)。只能针对对象或引用和指针const调用成员函数。例如,您不会修改本地对象,因此应声明为. 您清楚地修改了本地对象,因此运算符应该是.constconstoperator +()constoperator =()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);
    }
};

EDIT OP 想看看赋值运算符链是如何工作的。下面演示了这是如何做到的:

a = b = c;

相当于这个:

b = c;
a = b;

而且这并不总是等同于:

a = c;
b = c;

示例代码

#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;
}

输出

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
于 2012-12-26T23:24:13.687 回答
6

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

此外,该typedef struct { ... } name;模式是 C 主义,在 C++ 中没有太多位置。

要回答关于 的问题inline,在这种情况下没有区别。在结构/类定义中定义方法时,它被隐式声明为内联。当您显式指定inline时,编译器实际上会忽略它,因为该方法已被内联声明。

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

于 2012-12-26T22:46:13.047 回答
4

尝试这个:

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);
    }
 };  
于 2012-12-26T23:01:30.373 回答
3
  1. bool operator==(pos a) const{ - 此方法不会更改对象的元素。
  2. bool operator==(pos a) { - 它可能会改变对象的元素。
于 2012-12-26T22:59:04.787 回答