确保抽象低音 class 是 shared_ptr
Ensure abstract bass class is a shared_ptr
我有一个抽象基础class:
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
设为工厂 class 或方法:
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();
这确实需要您重写任何现有的派生 classes。
在 的基础上,我们还可以使 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();
我有一个抽象基础class:
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
设为工厂 class 或方法:
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();
这确实需要您重写任何现有的派生 classes。
在 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();