如何解决如何始终通过某种方法来强制执行该构造?
我有一些第三方抽象基类
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
参数,但是您不能创建一个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
设为不可重用std::unique_ptr
来强制执行正确性。删除复制ctor,放入您在构造中设置的私有bool标志,并在移出时清除,然后在make
内部对其进行检查。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。