![](/img/trans.png)
[英]Vector of shared_ptr of a abstract bass class pointing to derived classes
[英]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.