在编写运算符时需要了解一些事项,这些事项不常与其他函数一起使用。
例如,赋值运算符将return *this,因为您更改了向量的值:
class v {
public:
double x_, y_;
v& operator += (const v& rhs)
{
_x += rhs._x;
_y += rhs._y;
return *this;
}
};
另一个有趣的是,前++ 和后++ 不同只是因为一个未使用的参数:
class v {
public:
double x_, y_;
v& operator ++ (); // ++v
v& operator ++ (int); // v++
};
“等于”(赋值)是另一个在使用指针时比较棘手的问题。对于一个向量,一般不会有问题,但是如果你定义一个向量V并赋值给它自己,你就要小心了:
class v {
public:
double x_, y_;
v& operator = (const v& rhs)
{
if(this != &rhs)
{
x_ = rhs.x_;
y_ = rhs.y_;
}
return *this;
}
};
在你的情况下,if() 肯定不会有用,但考虑做这样的事情:
delete p_;
p_ = new foo;
p_->x_ = rhs.p_->x_;
如果&rhs == this,那么delete p_ 删除了rhs 指针!这意味着在第 3 行访问它是一个错误。
其余的应该很容易使用。比较运算符返回bool 并且是const:
class v {
public:
double x_, y_;
bool operator == (const v& rhs) const
{
return x_ == rhs.x_ && y_ == rhs.y_;
}
};
虽然,从 C++20 开始,您应该只声明三路比较运算符 <=>,它允许编译器为您实现所有其他比较运算符。这个返回一个负数(较小:a b)。
我不确定是什么让向量变大或变小,我在这个例子中使用了从 (0, 0) 开始的长度:
class v {
public:
double x_, y_;
int operator <=> (const v& rhs) const
{
if(x_ == rhs.x_ && y_ == rhs.y_)
{
return 0;
}
return length() > rhs.length() ? 1 : -1;
}
};
[] 运算符除外。该版本有两个版本:
class v {
public:
// I would imagine you'd use an array but as a simple example...
double x_, y_;
double operator [] (int idx) const
{
return idx == 0 ? x_ : y_;
}
v_ref operator [] (int idx)
{
v_ref v(this, idx);
return v;
}
};
如您所见,非常量版本的 [] 运算符返回一个引用。这是必要的,因此您可以编写如下内容:
r[3] = 7.3;
r[3] 返回该引用,然后以7.3 作为参数调用引用的赋值。 (请注意,如果您使用 3 作为索引,而您只有 2 个值:0 和 1,我们可能会抛出错误:此处未显示)
class v_ref
{
public:
v *p_;
int i_;
v_ref(v *p, int i)
: p_(p), i_(i)
{
}
operator = (double q)
{
// again, I suppose you'd use an array instead!
if(i_ == 0)
{
p_->x_ = q;
}
else
{
p_->y_ = q;
}
}
};
假设您想要一些安全性,向量指针可以使用引用计数器,以便您知道主向量对象是否在其所有引用对象之前被删除...
另一个注意事项:我想您的构造函数将分配一个 double 数组(或使用 std::vector<double> 类型...)如果您使用 new,请记住在析构函数中删除,那时 if() 在赋值运算符很重要。