此问题基于Create objects in conditional c++ statements。
但是,在我的情况下,我需要从多个类的选择中声明一个对象,然后将其作为参数传递给函数。因此,必须使用预定义名称(在这种情况下为 obj )声明对象。
Class1 obj;
Class2 obj;
if (...) {
obj = Class1(); }
if (...) {
obj = Class1(a, b); }
else
obj = Class2();
// Do something on declared object
DoSomething(obj.variable_);
当前,由于obj
的声明冲突,上述内容将不起作用。我应该怎么做?
答案 0 :(得分:4)
如果您的对象在运行时不必是“多态的”,则可能不需要std::variant
。将代码重构为:
if (...) {
DoSomething(Class1());
if (...) {
DoSomething(Class1(a, b));
else
DoSomething(Class2());
然后将DoSomething
用作模板或重载集:
void DoSomething(const Class1&) { }
void DoSomething(const Class2&) { }
答案 1 :(得分:1)
您可以使用std::variant
。
std::variant<Class1, Class2> var;
if (...) {
var = Class1(); }
if (...) {
var = Class1(a, b); }
else
var = Class2();
std::visit([](auto&& obj) { DoSomething(obj.variable_); }, var);
该变体一次可以容纳其中一种,这正是您所需要的。并且std::visit
允许您将代码通用地应用于任何一种选择,只要可以将通用lambda应用于它即可。
答案 2 :(得分:0)
OP说:“ Class1和Class2可以从通用基类继承。我可以提供DoSomething的重载”
继承可以。但仅当它以“子类型化”形式出现时。假设每个人都知道这一点。规范的例子。
在这种情况下,OP的问题和代码实际上是工厂方法的内部。一种解决方案可能是:
Interface::ptr make ( Interface::subtype which)
{
if ( which == Interface::subtype::one )
return std::make_unique<Class1>();
return std::make_unique<Class2>();
}
用法很简单:
Interface::ptr one = make( Interface::subtype::one ) ;
Interface::ptr two = make( Interface::subtype::two ) ;
one->do_something() ;
two->do_something() ;
仅是常见概念的一种变体。 Working code is here。
不需要多态性的选项
始终是一个不错的选择。我们不需要继承。我们只需要能够理解消息do_something()
的实例即可。
// no inheritance required
template<typename T>
void do_something( T the_t_ ) { the_t_.do_something(); }
同上
if ( ... ) {
do_something(Class1{}) ;
}
else if ( ... ) {
do_something(Class1(a,b)) ;
} else {
do_something(Class2());
}
在这种情况下,Class1和Class2不需要通用的基本类型。
ps:Vittorio的解决方案非常好。当Class1和Class2完全不相关时,也可以应用它。
该变体的一个有趣变体可能是:
if (...) {
Class1();
if (...) {
Class1(a, b);
else
Class2();
没有函数重载DoSomething()
,而是键入“做某事”的实例。可能是最可行的设计,但仅适用于某些应用程序。
答案 3 :(得分:0)
使用简单多态性的解决方案,
ClassBase () {
}
Class1 : ClassBase (){
}
Class2 : ClassBase (){
}
然后您可以像使用
ClassBase obj;
if (...) {
obj = Class1(); }
if (...) {
obj = Class1(a, b); }
else
obj = Class2();
// Do something on declared object
DoSomething(obj.variable_);