第一次学习用C++ 的运算符重载,记录一下报错的解决方法以及改进过程。

针对vector容器,有一个判断给定元素是否在vector中的函数:std::find(vec.cbegin(), vec.cend(), element);

但这个函数只能用在vector元素为内置类型的时候,如果vector 元素类型为类或者结构体,则需要在类或者结构体中重载 == 运算符。

version1:报错 bool must take exactly one argument == operator implementation file [duplicate]

// struct //
struct NeighborPointIdxPair
{
    int index1;
    int index2;
    bool operator==(const NeighborPointIdxPair & pair1, const NeighborPointIdxPair & pair2)
    {
        return (pair1.index1 == pair2.index1 &&
                pair1.index2 == pair2.index2)||
               (pair1.index1 == pair2.index2 &&
                pair1.index2 == pair2.index1);
    }
};

在stackoverflow 上找到了答案:https://stackoverflow.com/questions/32685139/bool-must-take-exactly-one-argument-operator-implementation-file

You are comparing the implicit this object to the other object

改为version2,如下。

:在《C++Primer》 上也看到过重载 operator== 不用this,用两个形参的 (p497),就像version1 一样,为什么我的就报错呢,还不明白具体原因,再研究==

version2:报错:error: passing xxx as 'this' argument of xxx discards qualifiers

// struct //
struct NeighborPointIdxPair
{
    int index1;
    int index2;
    bool operator==(const NeighborPointIdxPair & pair)
    {
        return (pair.index1 == this->index1 &&
                pair.index2 == this->index2)||
               (pair.index1 == this->index2 &&
                pair.index2 == this->index1);
    }
};

原因是,成员函数通过一个名为this 的额外的隐式参数来访问调用它的哪个对象。当我们调用一个成员函数(如operator==)时,用请求该函数的对象地址初始化this。this 默认情况下是一个指向非常量对象常量指针,即this指针存储的地址不能变,但它指向的对象的内容可以变。那也就是说,不能在一个常量对象上调用普通的成员函数

但我在后面的函数中使用上面定义的结构体类型的对象时,我定义成了常量引用,因为我在函数中不会改变这个对象的值,这就是报错的原因!如下所示:

/*
****************************************************************
********** Check the existence in vector of a element **********
****************************************************************
*/

// true: element exists in vector; false: not in vector
bool inVector(
                const NeighborPointIdxPair & PIdxPair,
                const std::vector<NeighborPointIdxPair> & PIdxPairVec
                )
{
    // if (PIdxPairVec.empty())
    // {
    //     std::cout << "inVector(): The input vector is empty!" << std::endl;
    //     return (false);
    // }
    auto it = std::find(PIdxPairVec.cbegin(), PIdxPairVec.cend(), PIdxPair);
    return (!(it == PIdxPairVec.cend()));
}

解决方法就是应该把this 设置为指向常量的指针,有助于提高函数的灵活性。然而this是隐式的,不出现在参数列表中,所以C++的规定就是在成员函数的形参列表后面加上const关键字。

也就是将运算符重载函数声明为:常量成员函数(const member function)

因为在常量成员函数中,this 是指向常量的指针,所以常量成员函数不能改变调用它的对象的内容

常量对象,常量对象的引用和指针都只能调用常量成员函数。

将不会改变对象内容的成员函数设置为常量成员函数,有助于提高类/结构体使用的灵活性

详见 《C++Primer 第5版》p231

由此得到version3, 如下

 

version3:

// struct //
struct NeighborPointIdxPair
{
    int index1;
    int index2;
    bool operator==(const NeighborPointIdxPair & pair) const
    {
        return (pair.index1 == this->index1 &&
                pair.index2 == this->index2)||
               (pair.index1 == this->index2 &&
                pair.index2 == this->index1);
    }
};

 

但是这个还不够好,因为一个类或者结构体的某个操作是检查相等性,则应定义operator==; 有了operator==, 通常也需要 operator!=

                                                                                                                                                                         ------《C++Primer 第5版》p492

于是有了version 4

 

version 4:

// struct //
struct NeighborPointIdxPair
{
    int index1;
    int index2;
    bool operator==(const NeighborPointIdxPair & pair) const
    {
        return (pair.index1 == this->index1 &&
                pair.index2 == this->index2)||
               (pair.index1 == this->index2 &&
                pair.index2 == this->index1);
    }
    bool operator!=(const NeighborPointIdxPair & pair) const 
    {
        return (pair.index1 != this->index1 ||
                pair.index2 != this->index2)&&
               (pair.index1 != this->index2 ||
                pair.index2 != this->index1);
    }
};

相等运算符和不相等运算符中的一个应该把工作委托给另一个,这意味着其中一个运算符应该负责实际比较对象的工作,而另一个运算符只是调用哪个真正工作的运算符。                                                  ------《C++Primer 第5版》p498

于是有了version 5

 

version 5:

// struct //
struct NeighborPointIdxPair
{
    int index1;
    int index2;
    bool operator==(const NeighborPointIdxPair & pair) const
    {
        return (pair.index1 == this->index1 &&
                pair.index2 == this->index2)||
               (pair.index1 == this->index2 &&
                pair.index2 == this->index1);
    }
    bool operator!=(const NeighborPointIdxPair & pair) const 
    {
        return !(this->operator==(pair));
    }
};

这样好多了~

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐