返回更专业对象的最佳方法

时间:2014-08-20 14:59:20

标签: c++ oop

我有一个基类Base,其中包含多个子类,例如Child1Child2等。 在这个Base类中,我有一个返回指向BaseDefinition的指针的方法:

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

现在与Base的类树并行,BaseDefinition类也有子类:Child1DefinitonChild2DefinitionGetDefinition()实现{ {1}}将返回Child1

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

1 个答案:

答案 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_thisshared_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();