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

时间:2011-08-16 18:14:10

标签: c++ overloading overload-resolution

我有这段代码:

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();
}

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

5 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:1)

它没有选择错误的过载; const - 根据this是否为const来解决问题。在您的情况下,o不是const,因此选择非const重载。

你可以通过创建一个o的const引用来解决这个问题,例如:

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

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

IntSomething x;
ConstIntSomething y;
y = x;

这听起来不正确。为什么不允许你将const引用到非const引用?

答案 2 :(得分:1)

您的对象o必须是const对象,才能在其上调用const函数。否则编译器会正确地选择函数的非const版本。

答案 3 :(得分:0)

编译器根据将成为this的对象的常量选择要使用的重载。您可以使用static_casts = static_cast<const Other&>(o.some_function());

调用所需的版本

答案 4 :(得分:0)

您可能还希望复制在C ++ 0x标准库的容器中找到的新行为。像vector这样的容器现在有成员cbegin()cend()返回const_iterator,无论容器是const还是不是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();
    }
};