带有Java背景的C++,我想通过使用A
或B
两个实现之一来初始化C
类型的变量来设置一些多态代码。
我的问题是在堆栈上是否有一种简便的方法。我有一种情况,我只在方法主体内使用A
,并希望在函数末尾销毁它,因此触摸堆是可选的。
这是我在堆上的处理方式:
A* a = NULL;
if (p) {
B* b = new B();
b->setSomethingImplementationSpecific();
a = b;
}
else {
a = new C();
}
doSomething(a);
delete(a);
实际上,我可能会将其引入工厂方法中,并使用
auto_ptr
来避免delete(a)
。这可行,但是我可以在堆栈上吗?我的思维模式是这样的:
A* a = NULL;
if (p) {
B b;
b.setSomethingImplementationSpecific();
a = &b;
}
else {
C c;
a = &c;
}
doSomething(a);
现在,我不必费心
delete(a)
,但是doSomething(a)
将不起作用,因为B
或C
在超出范围时会被破坏。我一直在尝试找出一种使用三元运算符来完成其中一部分的方法,但是最后我既弄糟了语法,又获取了临时地址,所以我是对的,没有办法做这个?
A * const a = &(p ? B() : C());
首先建议关于在堆栈上实现多态性是否愚蠢的建议,但是大多数情况下,我试图独立于设计意义而更好地理解C / C++在此 Realm 的局限性。
最佳答案
您可以使用 std::aligned_union
干净地进行此操作:
template <typename...T>
using storage_t = typename std::aligned_union<0, T...>::type;
和一个自定义的
unique_ptr
删除器:struct placement_deleter {
template <typename T>
void operator () (T* ptr) const {
ptr->~T();
}
};
template <typename T>
using stack_ptr = std::unique_ptr<T, placement_deleter>;
产生用法:
storage_t<B, C> storage;
stack_ptr<A> a;
if (p) {
auto b = new (&storage) B();
a.reset(b);
b->setSomethingImplementationSpecific();
} else {
a.reset(new (&storage) C());
}
doSomething(*a);
See it live at Coliru。