如何通过某种方法强制建设?



我有一些第三方抽象基类

struct foo
{
virtual foo*job() = 0;
...
static void* make_space(size_t sizeofDerived);
};

我无法改变。类型foo的对象(以及所有派生类)只能使用放置新建创建/构造到foo::make_space()返回的内存中, 因为普通建筑,如

derived_from_foo z;                 // or
auto p = new derived_from_foo();

可能会导致不希望出现的问题(损坏内存,具体取决于编译器,正如我最终发现的那样)。所以我的问题:如何编写/设计派生类

struct bar  // still abstract, since foo::job() is not provided
: foo
{
...
template<typename Derived, typename...Args>
static Derived* create(Args&&...args)
{
return ::new(foo::make_space(sizeof(Derived)))
Derived(std::forward<Args>(args)...);
}
};

因此,构造类型bar的对象或通过bar::create()以外的任何其他方式从bar派生的任何类型的对象在运行时 (i) 编译或 (ii,不太理想)失败?

事实上,你可以强制执行它,但要付出代价。

考虑这个类:

class A
{
public:
class Tag
{
public:
Tag(const Tag&) = default;
Tag(Tag&&) = default;
private:
Tag() {}
friend class A;
};
A(Tag, int a, char b) : a(a), b(b) {}
int a;
char b;
template<typename T, typename ... Params>
static T* make(Params&& ... params)
{
return new T(Tag(), std::forward<Params>(params)...);
}
};

它的构造函数需要一个Tag参数,但你不能做一个Tag,它有一个私有构造函数。你可以从A派生,但也不能直接创建派生类的对象:它需要将Tag传递给它的父构造函数,而你不能创建一个。

因此,创建A对象或派生类的唯一方法是调用A::make


好吧,还有办法作弊

class B : public A
{
public:
B(Tag t, double q) : A(t, 42, 'z'), q(q) {
// cheating:
B* other = new B(t, 3.14);
}
double q;
};

如果这困扰您,您仍然可以通过在运行时强制Tag正确性,使不可重用 à lastd::unique_ptr。移除复制 ctor,放入您在施工时设置的私人布尔标志并在搬出时清除,然后在make内检查它。

相关内容

  • 没有找到相关文章

最新更新