二进制运算符在C ++中使用不同的数据类型进行重载

时间:2015-12-15 14:50:08

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

我正致力于用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 < node而非node < int。我是否需要为node < int定义单独的函数?

我也想模拟这个函数,以便我可以将任何东西(它本身都有比较运算符)与node s进行比较:

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

同样,这适用于T < node,但不适用于node < T。我是否需要为node < T以及上述函数定义函数?

TL; DR

如果我将运算符重载为bool operator<(const foo& lhs, const bar& rhs),我是否还需要定义bool operator<(const bar& lhs, const foo& rhs)以便操作数可以解决?模板函数如template<typename T> bool operator<(const foo& lhs, const T& rhs)

也是如此

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

2 个答案:

答案 0 :(得分:2)

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

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

因此int被称为lhsnode被称为rhs。这些名称与类型所在的运营商的哪一方相匹配。 lhs l eft h s ide且rhs r ight < strong> h 和 s ide。所以

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 <所有类型T < node::key提供T node <两侧writeEOF()public final void writeString(String out) throws IOException { byte[] bytes = out.getBytes(); int numOfMessages = bytes.length / (BUFFER_SIZE - 1); if (bytes.length > BUFFER_SIZE - 1) { for (int i = 0; i < numOfMessages; i++) { writeHeader(new RequestHeader(clientId, getNextRequestId(), RequestCommand.SEND_DATA, false, // false tells it that it is not the last message. (byte)(i + 1))); output.write(bytes, i * (BUFFER_SIZE - 1), (BUFFER_SIZE - 1) )); writeEOF(); // tells the server to return the current buffer, and expect a new message. While it is not the last message, it just appends the buffered message to a StringBuilder RequestHeader header = handleHeader(); if (header == null || header.getRequestCommand() != RequestCommand.ACK) { throw new IOException("Failed to send message: " + lastRequestId); } } writeHeader(new RequestHeader(clientId, getNextRequestId(), RequestCommand.SEND_DATA, true, (byte) (numOfMessages))); output.write(bytes, numOfMessages * (BUFFER_SIZE - 1), bytes.length - (numOfMessages * (BUFFER_SIZE - 1))); writeEOF(); RequestHeader header = handleHeader(); if (header == null || header.getRequestCommand() != RequestCommand.ACK) { throw new IOException("Failed to send message: " + lastRequestId); } } else { writeHeader(new RequestHeader(clientId, getNextRequestId(), RequestCommand.SEND_DATA, (byte) 0)); output.write(bytes); writeEOF(); RequestHeader header = handleHeader(); if (header == null || header.getRequestCommand() != RequestCommand.ACK) { throw new IOException("Failed to send message"); } } } 出现的所有类型。

答案 1 :(得分:1)

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

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){}

要特定于您的问题,如果您希望只有一个模板比较功能,您可以按照以下方式执行:

    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;
}
  

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

{{1}}

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