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++中的类/结构声明所不需要的.您的成员不了解pos
as-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)
这将分配c
给b
,然后将结果值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
构件声明调用该成员将不修改底层对象(可变声明不耐受).只能const
对const
对象或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)
而不是typedef struct { ... } pos;
你应该做的struct pos { ... };
.这里的问题是您pos
在定义之前使用类型名称.通过将名称移动到结构定义的顶部,您可以在结构定义本身中使用该名称.
此外,该typedef struct { ... } name;
模式是C-ism,并且在C++中没有多少位置.
要回答你的问题inline
,这种情况没有区别.在struct/class定义中定义方法时,它是内联隐式声明的.当您明确指定时inline
,编译器会有效地忽略它,因为该方法已经内联声明.
(inline
如果在多个目标文件中定义了相同的方法,方法将不会触发链接器错误;链接器将简单地忽略除了其中一个之外的所有方法,假设它们都是相同的实现.这是内联方法中唯一保证的行为更改现在,它们不会影响编译器关于是否内联函数的决定;它们只是简化了所有翻译单元中的函数实现的可用性,这使得编译器可以选择内联函数,如果它决定它将是有益的这样做.)
尝试这个:
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)