[英]Ensure abstract bass class is a shared_ptr
I have an abstract base class: 我有一个抽象基类:
struct Base : std::enable_shared_from_this<Base>
{
virtual ~Base() = default;
virtual void foo() = 0;
void bar() {
baz(shared_from_this());
}
};
The only valid use case for Base
is to live in a shared_ptr
- bar
is an important method. 唯一有效的使用情况
Base
是生活在一个shared_ptr
- bar
是一个重要的方法。 How can I ensure that the following is impossible: 我如何确保以下操作是不可能的:
struct BadDerived : Base {
void foo() override { ... }
};
BadDerived bd;
bd.bar();
One technique is to make the constructor of Base
private and friend
a factory class or method: 一种技术是使
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>();
}
Usage: 用法:
struct Impl {
void foo(Base* self) { std::cout << "Hello!" << std::endl; }
};
auto gd = makeDerived<Impl>();
gd->bar();
This does require you to rewrite any existing derived classes. 这确实需要您重写任何现有的派生类。
Building off of ecatmur's answer , we could also make Base
constructible from a type that only has a private constructor: 根据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{});
}
Every Derived
type will have to take an extra constructor argument of type PrivateT
that it will have to forward through... but it will still be able to inherit from Base
! 每个“
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.