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. 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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With