【问题标题】:In c++, why does the compiler choose the non-const function when the const would work also? [duplicate]在 c++ 中,为什么编译器在 const 也可以工作时选择非常量函数? [复制]
【发布时间】:2010-09-14 21:55:28
【问题描述】:

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

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 函数中的某些变量,请使用相互属性。
  • ...和“成员变量”,我猜。

标签: c++ constants overload-resolution const-reference const-method


【解决方案1】:

两个答案浮现在脑海:

  1. 非常量版本更匹配。

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

您可以通过将a 转换为const Foo * 来使其使用其他重载。

编辑:来自C++ Annotations

之前,在第 2.5.11 节中的概念 函数重载是 介绍了。它注意到该成员 函数可以仅通过重载 他们的 const 属性。在那些情况下, 编译器将使用该成员 函数最接近匹配 对象的 const 限定:

【讨论】:

    【解决方案2】:

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

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

    如果你同时有一个 const 和一个非常量重载,并且想在一个非常量对象上调用 const ,这可能表明设计不好。

    【讨论】:

    • 完整的设计很难用一个例子来表达,但有几点可以改进,我敢肯定……我们目前做的是 const 指针方法,但它很难看,更重要的是依赖程序员记住这样做。
    • 给 const 重载一个不同的名字怎么样?或者有一个 const 重载和一个不同命名的函数,一个调用另一个内联?
    • 只是一点点选择...指针不是 const...在您的示例中它是“指向 const 的指针”。
    【解决方案3】:

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

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

    或

    b->Name() = "me";
    

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

    【讨论】:

    • 问题不在于返回值的常量与否,而在于对象的常量。 -1 不是我。
    • 我了解编译器的潜在问题,但我认为它可以进行一些简单的检查,例如在示例中,它会立即使用返回作为副本,然后丢弃它。
    • 那将是非常危险的,因为对其他代码行的更改也会导致该特定调用的行为发生更改。确定重载解决方案的规则本身就足够复杂了。
    【解决方案4】:

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

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

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

    【讨论】:

    • 我意识到使用 setName() 函数可能会更好,但同样,这个例子有点做作。实际上,我们有包含其他对象的指针对象,并且希望在可能的情况下返回 const 指针,当它们以“int c = a->B()->GetC();”等形式串在一起时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 2014-04-20
    • 2015-10-20
    • 1970-01-01
    • 2014-04-12
    • 2019-02-01
    相关资源
    最近更新 更多