重写专门女儿中的模板函数 class

Overriding template function in specialized daughter class

我有一个模板化的 class MatchBase,其中包含运算符 == 的函数

template<typename Element>
class MatchBase{
    virtual bool operator ==(const MatchBase<Element>& m) const{
    if(_v1 == m.getFirst() && _v2 == m.getSecond()){
        return true;
    }
    return false;
}

我知道有一个女儿class 模板专用的匹配。用于专业化的 class Place 没有 operator== 来进行比较。因此,我试图覆盖 operator== 以使用 class 地方。

关于我尝试过的事情:

class Match : public betterGraph::MatchBase<graphmatch::Place>{
public :
    Match(const graphmatch::Place& v, const graphmatch::Place& vv) : 
        betterGraph::MatchBase<graphmatch::Place>(v, vv) 
        {};

    virtual bool operator ==(const Match& m) const{
        if(_v1.mass_center == m.getFirst().mass_center && _v2.mass_center == m.getSecond().mass_center){
            return true;
        }
        return false;
    }

};

我也试过了

virtual bool operator ==(const betterGraph::MatchBase<graphmatch::Place>& m) const{
    if(_v1.mass_center == m.getFirst().mass_center && _v2.mass_center == m.getSecond().mass_center){
        return true;
    }
    return false;
}

但我总是遇到以下类型的错误:

error: no match for ‘operator==’ (operand types are ‘const AASS::graphmatch::Place’ and ‘const AASS::graphmatch::Place’)
if(_v1 == m.getFirst() && _v2 == m.getSecond()){

因为它试图从 Base class.

编译方法

我有什么办法可以覆盖女儿 class 中基 class 的这个功能吗?我已经阅读了问题 here 但这里是专门的方法,而我的 class 是专门的,所以我不知道如何进行前向声明:/.

该函数可能是虚函数,但在您继承基函数时它仍会被初始化 class。 这很重要,因为您可能会这样写:

MatchBase<Place> test = Match(p1,p2);

MatchBase<Place>Match 的基础 class 但它们并不相同。 调用 MatchBase<Place>::operator==() 仍将调用模板库中定义的函数 class.

您现在有多种选择: - 使基 class 中的函数成为纯虚函数 - 实施 Place::operator==() - 将一个比较器作为参数传递给你的基础 class 作为参数

前两个应该清楚(如果不清楚请询问)。对于第三种,这可能是一种可行的方法:

template<typename Element, typename Less = std::less<Element>>
class MatchBase {

protected:
    Element _v1;
    Element _v2;

public:
    MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
    {}

    virtual bool operator ==(const MatchBase<Element, Less>& m) const {
        Less less;
        bool v1Equal = !less(_v1, m.getFirst()) && !less(m.getFirst(), _v1);
        bool v2Equal = !less(_v2, m.getSecond()) && !less(m.getSecond(), _v2);
        return v1Equal && v2Equal;
    }

    const Element& getFirst() const { return _v1; }
    const Element& getSecond() const { return _v2; }

};

struct Place
{
    int mass_center;
};

struct PlaceLess
{
    bool operator()(const Place& p1, const Place& p2) 
    {
        return p1.mass_center < p2.mass_center; 
    };
};

class Match : public MatchBase <Place, PlaceLess>
{
public:
    Match(const Place& v, const Place& vv) :
        MatchBase<Place, PlaceLess>(v, vv)
    {};
};

另一种方法可能是在这种情况下专门研究 std::less<T>。所以你不需要将它作为模板参数传递。

template<typename Element>
class MatchBase {

protected:
    Element _v1;
    Element _v2;

public:
    MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
    {}

    virtual bool operator ==(const MatchBase<Element>& m) const {
        std::less<Element> less;
        bool v1Equal = !less(_v1, m.getFirst()) && !less(m.getFirst(), _v1);
        bool v2Equal = !less(_v2, m.getSecond()) && !less(m.getSecond(), _v2);
        return v1Equal && v2Equal;
    }

    const Element& getFirst() const { return _v1; }
    const Element& getSecond() const { return _v2; }

};

struct Place
{
    int mass_center;
};

template<>
struct std::less<Place>
{
    bool operator()(const Place& p1, const Place& p2) 
    {
        return p1.mass_center < p2.mass_center; 
    };
};

class Match : public MatchBase <Place>
{
public:
    Match(const Place& v, const Place& vv) :
        MatchBase<Place>(v, vv)
    {};
};

当然,您可以合并这些方式,这样您就可以在需要时覆盖 Less 模板参数。

如果您不打算使用预定义类型(考虑 intstd::string 等...),您还可以确保 class 作为 Element 必须继承 class/struct 强制实施 operator==

template <typename T>
struct IComparable
{
    virtual bool operator==(const T& other) const = 0;
};


template<typename Element>
class MatchBase {

    static_assert(std::is_base_of<IComparable<Element>, Element>::value, "Element must implement comparable");

protected:
    Element _v1;
    Element _v2;

public:
    MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
    {}

    virtual bool operator ==(const MatchBase<Element>& m) const {
        return _v1 == m._v1 && _v2 == m._v2;
    }
};

struct Place : public IComparable<Place>
{
    int mass_center;

    bool operator==(const Place& other) const
    {
        return mass_center == other.mass_center;
    };
};

class Match : public MatchBase <Place>
{
public:
    Match(const Place& v, const Place& vv) :
        MatchBase<Place>(v, vv)
    {};
};