C++ 在c++;,为什么编译器选择非常量函数,而常量也可以工作?
例如,假设我有一个类:C++ 在c++;,为什么编译器选择非常量函数,而常量也可以工作?,c++,constants,overload-resolution,const-reference,const-method,C++,Constants,Overload Resolution,Const Reference,Const Method,例如,假设我有一个类: 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_
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
Foo*a;
//做些事情。。。
std::string name=a->name();// 我想到两个答案:
非常量版本更接近
如果它为非常量情况调用常量重载,那么在什么情况下它会调用非常量重载
通过将a
强制转换为const Foo*
,可以让它使用另一个重载
编辑:来自
前面,在第2.5.11节中
函数重载的定义是
介绍。在那里,它注意到该成员
函数可能仅通过
它们的常量属性。在这些情况下,
编译器将使用该成员
函数与
对象的常量限定:
因为a不是常量指针。因此,非常量函数更接近匹配。以下是如何调用const函数:
const Foo* b = a;
std::string name = b->Name();
如果您同时具有常量和非常量重载,并且希望在非常量对象上调用常量重载,这可能表明设计不好。编译器在确定时没有考虑您如何使用返回值;这不是规则的一部分。它不知道你在做什么
std::string name = b->Name();
或
它必须选择在这两种情况下都适用的版本。您可以添加一个与“Name()const”等效的“cName”函数。通过这种方式,您可以调用函数的const版本,而无需首先强制转换到const对象
这对于C++0x中的新关键字auto非常有用,这就是为什么他们要更新库以包括cbegin()、cend()、crbegin()、crend()以返回常量迭代器,即使对象是非常量
最好使用setName()函数来更改名称,而不是返回对底层容器的引用,然后“可能”对其进行修改。问题不在于返回值的常量与否,而在于对象的常量。虽然-1不是我。我理解编译器可能存在的问题,但我认为它能够进行一些简单的检查,例如在示例中,它将立即使用返回值来获取副本,然后丢弃它。这将非常危险,因为对其他代码行的更改也会导致该特定调用的行为发生更改。确定过载分辨率的规则已经够复杂了。完整的设计很难用一个例子来表达,但我相信有几点可以改进。。。我们目前使用的是const指针方法,但它很难看,更重要的是依赖于程序员记住这样做。给const重载一个不同的名称如何?或者同时有一个常量重载和一个不同名称的函数,一个调用另一个,这是一个错误。。。指针不是常量。。。在您的示例中,它是一个“指向常量的指针”。我知道使用setName()函数可能会更好,但同样,这个示例有些做作。实际上,我们有包含其他对象的指针对象,并且希望在可能的情况下返回常量指针,将它们串成“int c=a->B()->GetC();”等。如果您想更改常量函数中的一些变量,我想可以使用mutual属性…和“member variables”。
b->Name() = "me";