我有这段代码:
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()
的名称。
答案 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_cast
:s = 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();
}
};