返回更专门化对象的最佳方式

Best way to return more specialized object

本文关键字:最佳 方式 对象 专门化 返回      更新时间:2023-10-16

我有一个具有多个子类的基类Base,例如Child1, Child2等。在这个Base类中,我有一个方法返回一个指向BaseDefinition的指针:

virtual std::shared_ptr<BaseDefinition> GetDefinition() { return m_def; }

现在平行于Base的类树,BaseDefinition类也有子类:Child1Definiton, Child2Definition等。例如,Child1GetDefinition()实现将返回std::shared_ptr<Child1Definition>

然而,GetDefinition()的返回类型当然是std::shared_ptr<BaseDefinition>,只要我们有Base*指针,这也是完全正确的。但是假设我们有一个更特殊的指针,例如Child1*,在这种情况下,Child1::GetDefinition()的返回类型应该是std::shared_ptr<Child1Definition>。一个人怎样才能达到这种行为呢?

类似如下:

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()是一个协变返回类型的私有虚函数。协变返回类型特性仅适用于普通指针或引用。虚函数可以被派生类重写,而不管它们的访问权限是什么(private/protected/public)。

GetDefinition是它的公共非虚拟包装器,其唯一目的是将普通指针包装成智能指针。该函数由每个派生类定义。它隐藏了它的基类版本。

std::enable_shared_from_thisshared_from_this()需要在这里从shared_ptr<X>到普通X*,然后正确地返回到shared_ptr<X>

基本上,这个精巧的装置模拟了智能指针的协变返回类型。例如:
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();