带有Java背景的C++,我想通过使用AB两个实现之一来初始化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)将不起作用,因为BC在超出范围时会被破坏。

我一直在尝试找出一种使用三元运算符来完成其中一部分的方法,但是最后我既弄糟了语法,又获取了临时地址,所以我是对的,没有办法做这个?
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

09-25 20:36