【发布时间】:2013-03-19 11:23:30
【问题描述】:
我想创建一个重载函数,这些函数接受一个指向基类和派生类的共享指针。它似乎适用于引用和原始指针,但不适用于额外派生类的共享指针。见示例代码:
#include <memory>
class Base{};
class Derived : public Base {};
class ExtraDerived : public Derived {};
bool IsBase(Base*){ return true; }
bool IsBase(Derived*){ return false; }
bool IsBase(std::shared_ptr<Base>){ return true; }
bool IsBase(std::shared_ptr<Derived>){ return false; }
int main()
{
auto derived = std::make_shared<Derived>();
auto extra_derived = std::make_shared<ExtraDerived>();
// works
auto raw_result_derived = IsBase(derived.get());
auto raw_result_extra_derived = IsBase(extra_derived.get());
auto shared_result_derived = IsBase(derived);
// doesn't work
auto shared_result_extra_derived = IsBase(extra_derived);
}
在使用 Visual Studio 2012 时,我得到:“错误 C2668:'IsBase':对重载函数的模糊调用”,但当我在此处尝试代码时也得到相同的结果 http://ideone.com/6uoa0p。
这似乎不是理想的行为(因为它适用于“原始”内容)。这是模板的限制吗,还有其他原因导致这不起作用还是错误? 我怎样才能让它以最不难看的方式工作?
我能想到的最好的是
//ugly workaround
bool IsBase(std::shared_ptr<Base>, Base*){ return true; }
bool IsBase(std::shared_ptr<Derived>, Derived*){ return false; }
template<typename T> bool IsBase(std::shared_ptr<T> input )
{
return IsBase(input, input.get());
}
【问题讨论】:
-
你为什么要那个?只需提供基函数,它就会愉快地接受派生类指针。如果你想捕获派生类对象,你的方法无论如何都不会工作,因为它需要对函数参数的动态类型进行调度才能正确完成。如果程序员在传递之前将
Ptr<Derived>隐式转换为Ptr<Base>,那么这种重载方法就会失效。 -
@JohannesSchaub-litb 我没有想到那种情况。我可能不得不重新考虑我想要什么。
标签: c++ inheritance c++11 shared-ptr overloading