C++编译器选择类成员函数的错误重载

C++ compiler picking the wrong overload of a class member function

本文关键字:错误 重载 函数 成员 编译器 选择 C++      更新时间:2023-10-16

我有这个代码:

template <class T>
class Something
{
    T val;
public:
    inline Something() : val() {}
    inline Something(T v) : val(v) {}
    inline T& get() const { return val; }
    inline Something& operator =(const Something& a) { val = a.val; return *this; }
};
typedef Something<int> IntSomething;
typedef Something<const int> ConstIntSomething;
class Other
{
public:
    IntSomething some_function()
    {
        return IntSomething(42);
    }
    ConstIntSomething some_function() const
    {
        return ConstIntSomething(42);
    }
};
void wtf_func()
{
    Other o;
    ConstIntSomething s;
    s = o.some_function();
}

但是,编译器在wtf_func()中选择了错误的Other::some_function()重载(即非常量重载(。我该如何解决这个问题?请注意,由于某些原因,我无法更改Other::some_function()的名称。

o不是常量限定的,因此选择了非常量some_function。 如果要选择常量限定的重载,则需要将常量限定符添加到o

Other o;
Other const& oref(o);
ConstIntSomething s;
s = oref.some_function();

当发生重载解析时,编译器只查看o.some_function()子表达式;它不会查看函数调用周围的上下文来决定选择其他内容。 此外,在重载解析期间不考虑成员函数的返回类型。

请注意,IntSomething隐式转换为ConstIntSomething可能更有意义,要么在IntSomething中使用operator ConstIntSomething()重载(不太好(,要么在ConstIntSomething中使用非显式ConstIntSomething(IntSomething const&)构造函数(更好(。

它不会选择错误的重载; const -ness 由this是否const来解决。 在您的情况下,o是非const,因此选择非const重载。

您可以通过创建对o的常量引用来破解它,例如:

const Other &o2 = o;
s = o2.some_function();

但实际上,您可能应该考虑Something中的过载。 例如,您当前无法执行此操作:

IntSomething x;
ConstIntSomething y;
y = x;

这听起来不正确。 为什么不应该允许你把一个常量引用带到一个非常量引用?

您的对象o需要const对象才能在其上调用const函数。 否则,编译器会正确选取函数的非 const 版本。

编译器根据

将变得this的对象的恒定性来选择要使用的重载。您可以使用static_casts = static_cast<const Other&>(o.some_function());

您可能

还想复制在 C++0x 标准库的容器中找到的新行为。像 vector 这样的容器现在具有成员cbegin()cend(),它们返回一个const_iterator,无论容器是否是常量,这与 begin()end() 不同

class Other {
    // Rest of other
public:
    // No overload for non-const
    // Even if called with a non const Other, since this member is marked
    // const, this will be of type Other const * in all cases and will call
    // the const qualified overload of some_function.
    ConstIntSomething csome_function() const
    {
        return some_function();
    }
};