簡體   English   中英

確保抽象低音類是shared_ptr

[英]Ensure abstract bass class is a shared_ptr

我有一個抽象基類:

struct Base : std::enable_shared_from_this<Base> 
{
    virtual ~Base() = default;
    virtual void foo() = 0;

    void bar() {
        baz(shared_from_this());
    }
};

唯一有效的使用情況Base是生活在一個shared_ptr - bar是一個重要的方法。 我如何確保以下操作是不可能的:

struct BadDerived : Base {
    void foo() override { ... }
};

BadDerived bd;
bd.bar(); 

一種技術是使Base的構造函數私有並成為工廠類或方法的friend

struct Base : std::enable_shared_from_this<Base> 
{
    virtual ~Base() = default;
    virtual void foo() = 0;

    void bar() {
        baz(shared_from_this());
    }

private:
    template<class Impl> friend std::shared_ptr<Base> makeDerived();
    Base() {}
};

template<class Impl>
std::shared_ptr<Base> makeDerived() {
    struct Derived : Base, Impl {
        void foo() override { Impl::foo(static_cast<Base*>(this)); }
    };
    return std::make_shared<Derived>();
}

用法:

struct Impl {
    void foo(Base* self) { std::cout << "Hello!" << std::endl; }
};
auto gd = makeDerived<Impl>();
gd->bar();

這確實需要您重寫任何現有的派生類。

根據ecatmur的答案 ,我們還可以從僅具有私有構造函數的類型使Base可以構造:

class PrivateT {
    PrivateT() { }

    template <typename Impl, typename... Args>
    friend std::shared_ptr<Impl> makeDerived(Args&&... );
};

struct Base : std::enable_shared_from_this<Base> {
    Base(PrivateT ) { }
    virtual void foo() = 0;

    void bar() {
        baz(shared_from_this());
    }
};

template <typename Impl, typename... Args>
std::shared_ptr<Impl> makeDerived(Args&&... args) {
    return std::make_shared<Impl>(std::forward<Args>(args)...,
        PrivateT{});
}

每個“ Derived類型都必須采用類型為PrivateT的額外構造函數參數,該參數必須轉發通過……但仍將能夠從Base繼承!

struct Impl : Base {
    Impl(PrivateT pt) : Base(pt) { }
    void foo() override { std::cout << "Hello!" << std::endl; }
};

auto gd = makeDerived<Impl>();
gd->bar();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM