20

例如,假设我有一个类:

class Foo
{
public:
    std::string& Name()
    {
        m_maybe_modified = true;
        return m_name;
    }

    const std::string& Name() const
    {
        return m_name;
    }
protected:
    std::string m_name;
    bool m_maybe_modified;
};

在代码的其他地方,我有这样的东西:

Foo *a;
// Do stuff...
std::string name = a->Name(); // <-- chooses the non-const version

有谁知道为什么编译器会在这种情况下选择非常量版本?

这是一个有点做作的例子,但我们试图解决的实际问题是定期自动保存一个对象,如果它已经改变,并且指针必须是非常量的,因为它可能会在某个时候改变。

4

4 回答 4

18

脑海中浮现出两个答案:

  1. 非常量版本是更接近的匹配。

  2. 如果它为非常量情况调用 const 重载,那么在什么情况下它会调用非常量重载?

您可以通过强制转换aconst Foo *.

编辑:来自C++ 注释

早些时候,在 2.5.11 节中介绍了函数重载的概念。那里指出,成员函数可能仅通过其 const 属性重载。在这些情况下,编译器将使用与对象的 const 限定最匹配的成员函数:

于 2008-10-02T19:30:20.333 回答
18

因为 a 不是 const 指针。因此,非常量函数是更接近的匹配。以下是调用 const 函数的方法:

const Foo* b = a;
std::string name = b->Name();

如果您同时具有 const 和非常量重载,并且想在非常量对象上调用 const 重载,则这可能表明设计不佳。

于 2008-10-02T19:31:59.363 回答
7

编译器在确定时不会考虑您如何使用返回值;这不是规则的一部分。它不知道你是否在做

std::string name = b->Name();

或者

b->Name() = "me";

它必须选择适用于这两种情况的版本。

于 2008-10-02T19:46:58.890 回答
2

您可以添加一个等效于“Name() const”的“cName”函数。这样,您可以调用函数的 const 版本,而无需先转换为 const 对象。

这对于 C++0x 中的新关键字 auto 非常有用,这就是为什么他们更新库以包含 cbegin()、cend()、crbegin()、crend() 以返回 const_iterator,即使对象不是非常量。

您正在做的事情可能最好通过一个 setName() 函数来完成,该函数允许您更改名称,而不是返回对底层容器的引用,然后“可能”它被修改。

于 2008-10-02T20:49:10.893 回答