我有一个基类Base
,其中包含多个子类,例如Child1
,Child2
等。
在这个Base
类中,我有一个返回指向BaseDefinition
的指针的方法:
virtual std::shared_ptr<BaseDefinition> GetDefinition() { return m_def; }
现在与Base
的类树并行,BaseDefinition
类也有子类:Child1Definiton
,Child2Definition
等GetDefinition()
实现{ {1}}将返回Child1
。
然而std::shared_ptr<Child1Definition>
的返回类型当然是GetDefinition()
,只要我们有std::shared_ptr<BaseDefinition>
指针,这也是完全正确的。但是假设我们有一个更专业的指针,例如Base*
,在这种情况下Child1*
的返回类型应为Child1::GetDefinition()
。怎么能实现这种行为?
答案 0 :(得分:4)
如下所示:
struct BaseDefinition : std::enable_shared_from_this<BaseDefinition> {};
class Base
{
private:
virtual BaseDefinition* DoGetDefinition() = 0; // covariant return type
public:
std::shared_ptr<BaseDefinition> GetDefinition() {
return std::static_pointer_cast<BaseDefinition>(this->DoGetDefinition()->shared_from_this());
}
};
struct DerivedDefinition : BaseDefinition {};
class Derived : public Base
{
private:
virtual DerivedDefinition* DoGetDefinition() override = 0; // covariant return type
public:
std::shared_ptr<DerivedDefinition> GetDefinition() {
return std::static_pointer_cast<DerivedDefinition>(this->DoGetDefinition()->shared_from_this());
}
};
这里,DoGetDefinition()
是具有协变返回类型的私有虚函数。协变返回类型功能仅适用于普通指针或引用。无论访问类是什么(私有/受保护/公共),派生类都可以覆盖虚函数。
GetDefinition
是一个公共的非虚拟包装器,其唯一目的是将普通指针包装成智能指针。此函数由每个派生类定义。它隐藏了它的基类版本。
std::enable_shared_from_this
和shared_from_this()
从shared_ptr<X>
转到普通X*
,然后再回到shared_ptr<X>
。
基本上,这个装置模拟了智能指针的协变返回类型。 E.g:
Derived a;
// Get Base stuff if accessing through Base.
Base* b = &a;
std::shared_ptr<BaseDefinition> p = b->GetDefinition(); // Calls Derived::DoGetDefinition
// Get Derived stuff if accessing through Derived.
Derived* d = &a;
std::shared_ptr<DerivedDefinition> q = d->GetDefinition();