c++ - 如何始终通过某种方法强制执行该构造?
问题描述
我有一些第三方抽象基类
struct foo
{
virtual foo*job() = 0;
...
static void* make_space(size_t sizeofDerived);
};
我无法改变。类型的对象foo
(和所有派生类)只能使用placement-new创建/构造到由返回的内存中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
bar::create()
的对象在(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
参数,但你不能制作 a Tag
,它有一个私有构造函数。您可以从 派生A
,但也不能直接创建派生类的对象:它需要将 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
不可重用 à la在运行时强制执行正确性std::unique_ptr
。删除复制 ctor,放入您在构造时设置并在移出时清除的私有 bool 标志,然后在内部检查它make
。
推荐阅读
- python - 按属性值范围过滤
- python - Pandas - 从时间序列数据中聚合列 10 毫秒
- javascript - Chrome 开发工具服务工作者错误图标/计数
- android - 少数 Android 版本 23 手机上的本机崩溃
- apache-spark - 写入 s3 或 gs 时设置 parquet.block.size 是否重要?
- angular - 以角度 6 调用内部文件阅读器时,Mat Snackbar 未正确显示
- swift - 如何使用共享代码对更有限的类版本进行建模?
- c - 我的 SAMA5D27 嵌入式板的 PUSH BUTTON 和 LED 的 C 代码有问题
- makefile - 生成文件函数
- r - 在 ggplot2 中使用 geom_pointrange 显示图例的问题