【问题标题】:Binary operator overloading in C++ with differing data types具有不同数据类型的 C++ 中的二元运算符重载
【发布时间】:2015-12-15 14:50:08
【问题描述】:

我正在用 C++ 实现 AVL 树。为了保持简洁(并且为了练习),我试图为树的节点重载比较运算符。

这就是我希望树的 find 函数的外观:

node* find(int key)
{
    node* currentNode = root;

    while (currentNode)
    {
        if (key < *currentNode)
        {
            currentNode = currentNode.getLeftChild();
        }
        else if (key > *currentNode)
        {
            currentNode = currentNode.getRightChild();
        }
        else
        {
            return currentNode;
        }
    }

    return nullptr;
}

在这种情况下,我可以重载运算符以将intnode 进行比较,如下所示:

bool operator<(const int& lhs, const node& rhs)    // friend of node
{
    return lhs < rhs.key;
}

但这似乎只适用于int &lt; node,不适用于node &lt; int。我需要为node &lt; int 定义一个单独的函数吗?

我还想将此函数模板化,以便我可以将任何东西(本身具有比较运算符)与nodes 进行比较:

template<typename T> bool operator<(const T& lhs, const node& rhs)    // friend of node
{
    return lhs < rhs.key;
}

同样,这适用于T &lt; node,但不适用于node &lt; T。我需要为node &lt; T定义一个函数以及上面的函数吗?

TL;DR

如果我将运算符重载为bool operator&lt;(const foo&amp; lhs, const bar&amp; rhs),我是否还需要定义bool operator&lt;(const bar&amp; lhs, const foo&amp; rhs) 以便操作数可以任意选择? template&lt;typename T&gt; bool operator&lt;(const foo&amp; lhs, const T&amp; rhs)这样的模板函数也是这样吗?

抱歉,如果我在这里回答了我自己的问题,但我能找到的关于运算符重载的唯一资源只显示了对两个参数使用相同类型的示例。我只是想确保我这样做是正确的,希望下次有人搜索此问题时会出现此帖子。

【问题讨论】:

  • 如果您想对这些类型进行可互换的比较,也许在它们之间定义一个转换运算符是有意义的?
  • 好主意!我从来没有想过。

标签: c++ templates comparison operator-overloading avl-tree


【解决方案1】:

让我们看看你的功能和你正在使用的命名

bool operator<(const int& lhs, const node& rhs) 

所以int 被称为lhsnoderhs。这些名称与类型所在的运算符的哪一侧相匹配。 lhsleft hand side 和 rhsright h和side。所以

bool operator<(const int& lhs, const node& rhs) 

只有在你有的时候才会起作用

int < node

如果你想处理

node < int

然后您需要另一个函数,其中nodelhsintrhs

bool operator<(const node& lhs, const int& rhs) 

现在你可以像这样模板化

template<typename T> bool operator<(const T& lhs, const node& rhs)    // friend of node
{
    return lhs < rhs.key;
}

template<typename T> bool operator<(const node& lhs, const T& rhs)    // friend of node
{
    return lhs.key < rhs;
}

这将为您提供 operator &lt; 用于定义 T &lt; node::key 的所有类型,其中 Tnode 出现在 &lt; 的任一侧。

【讨论】:

  • 我试过这个并得到这个编译器错误:*snip*.cpp(74): error C2893: Failed to specialize function template 'bool operator &lt;(const node &amp;,const T &amp;)' *snip*.cpp(74): note: With the following template arguments: *snip*.cpp(74): note: 'T=node' *snip*.cpp(74): error C2893: Failed to specialize function template 'bool operator &lt;(const T &amp;,const node &amp;)' *snip*.cpp(74): note: With the following template arguments: *snip*.cpp(74): note: 'T=int' *snip*.cpp(74): error C2677: binary '&lt;': no global operator found which takes type 'node' (or there is no acceptable conversion)
【解决方案2】:

它被认为是好的做法。许多图书馆开发人员都以同样的方式做到了这一点。 boost 就是这样一个例子,如果你分别定义这两个操作。

bool operator < (const foo& lhs, const bar& rhs);
bool operator < (const bar& lhs, const foo& rhs);

针对您的问题,如果您希望只有一个模板比较功能,您可以按照以下方式进行:

template<typename T>
bool less(const T& lhs, const T& rhs)
{
    return lhs < rhs;
}

class node
{
private:
    int nodeValue;

public:
    explicit node(int i):nodeValue(i){}

下面定义了与int比较的转换函数,同样可以 为 char 或用户定义的数据类型定义

    operator int()const
    {
        return nodeValue;
    }
};

void test()
{
    node tmp(75);

    std::cout<<"less<int>(tmp, 10):"<<less<int>(tmp, 10)<<std::endl;
    std::cout<<"less<int>(10, tmp):"<<less<int>(10, tmp)<<std::endl;
}

在此基础上,您可以将此方法用于两种不同的用户定义日期类型,前提是它们已将转换函数定义为定义了运算符 的某些数据类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-23
    • 2014-06-02
    • 2012-04-26
    相关资源
    最近更新 更多