在c ++中,为什么编译器在const工作时也会选择非const函数?

时间:2008-10-02 19:24:26

标签: c++ compiler-construction const

例如,假设我有一个班级:

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

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

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

4 个答案:

答案 0 :(得分:18)

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

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

如果你同时拥有const和非const重载,并且想要在非const对象上调用const,那么这可能表明设计不好。

答案 1 :(得分:16)

我想到了两个答案:

  1. 非const版本更接近匹配。

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

  3. 您可以通过将a投射到const Foo *来使用其他重载。

    修改:来自C++ Annotations

      

    早些时候,在第2.5.11节中概念   函数重载是   介绍。在那里它注意到该成员   函数可能仅仅被重载   他们的const属性。在那些情况下,   编译器将使用该成员   函数 匹配最紧密的   对象的const限定:

答案 2 :(得分:6)

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

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

b->Name() = "me";

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

答案 3 :(得分:0)

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

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

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