如何有条件地初始化c ++中的对象

时间:2012-01-30 07:20:19

标签: c++

class X {
   X(int, int); //constructor
   void func(); 
}

class Y {
  public int func() {
    X x(5,7); 
    // some other random operations. 
    x.func(); 
  }
}

现在,如果我必须根据某些条件初始化x,我该怎么做?

class Z {
 // only refer to x when mycond is true. 
  public int func(boolean mycond) {
    if(mycond) 
     X x(5,7); 
    //same random operations; 
    if(mycond) 
      x.func(); 
  }
}

以不美观的方式完成上述工作的一种方法是:

class Z {
  // only refer to x when mycond is true. 
  public int func(boolean mycond) {
    if(mycond)  {
       X x(5,7); 
     //same random operations; 
      x.func(); 
    }
    else  {
      //same random operations
    }
  }
}

我正在寻找更简单的东西,我不必重复代码。

6 个答案:

答案 0 :(得分:4)

在你给出的例子中,不清楚为什么你不能把它写成:

class Z {
    // only refer to x when mycond is true. 
    public:
    int func(bool mycond) {
        //same random operations; 
        if(mycond) {
            X x(5,7); 
            x.func();
        }
    }
};

但是,如果由于某种原因这是不可取的(例如,如果X的构造函数有一些必须在“某些随机操作”之前发生的副作用),那么你应该看看{{1} }:

boost::optional

如果由于某种原因您不想使用class Z { // only refer to x when mycond is true. public: int func(bool mycond) { boost::optional<X> x; if (mycond) x = X(5,7); //some random operations; if (mycond) x->func(); } }; ,那么使用boost::optional可以获得类似的效果:

union

也就是说,这将导致将名称引入范围,其中该名称有时仅具有意义。这是非常值得怀疑的,你应该考虑使用不同的设计。

答案 1 :(得分:2)

显而易见的答案是将其他随机操作放在一个单独的操作中 功能,所以你的代码变成:

int
func()
{
    if ( myCondition ) {
        X x( 5, 7 );
        otherOperations();
        x.func();
    } else {
        otherOperations();
    }
}

无论如何,你应该这样做,如果只是为了完成这个功能 可读和可维护。

答案 2 :(得分:1)

显而易见的解决方案是使用指针或自动指针:

class Z {
public:
  // only refer to x when mycond is true. 
  int func(boolean mycond) {
    std::auto_ptr<X> px;
    if(mycond)
       px = new X(5,7); 
    //same random operations; 
    if (px.get() != 0)
      px->func(); 
  }
}

答案 3 :(得分:0)

您可以将“随机操作”分解出来,就像这样

if (my_cond) X x(5, 7);
random_operations_factored_out(T& a, U& b, const W& c, ..); // all the references that you need
if (my_cond) X.func();

显然你可以(应该?)更好地封装上下文,为了一个例子,我使用了pass-by-reference。

另一种可能性是将逻辑封装在一对构造函数和析构函数中,如

class X_caller{
private:
  bool cond;
  X x;
public:
  X_caller(bool cond, int param1, int param2):cond(cond){ 
       if (cond) {x = X(param1, param2);}
  }
  ~X_caller(){
      if (cond) x.func();
  }
}

现在你将使用这个

{
X_caller(my_cond, 5, 7);
// all your operations

} // at the end of the scope the destructor of X_caller calls x.func() only if my_cond was true
  // but you "can't see" this function call if you don't know the body of X_caller, so be careful!
  // You have to document this kind of behaviour otherwise it's too obscure for future maintenance.

在所有情况下,您必须确保必须访问的所有资源(变量等)都可用于分解代码。

各种选择之间的平衡取决于代码的复杂性:总是尽量减少代码阅读器中的潜在混淆。这可能来自长时间重复的代码,或来自“隐藏”的调用或来自许多其他来源,如果可能,您应该尽量减少它。

答案 4 :(得分:0)

如何使用newpointer (*)

X *xPtr = 0;
class Z 
{   
    // only refer to xPtr when mycond is true.    
    public int func(boolean mycond) 
    {
        if(mycond)  
        {        
            xPtr = new X(5,7);       
        }

        //same random operations;                 

        if(xPtr)
        {
            xPtr.func();      
        }
    }

   // and don't forget delete xPtr;
} 

并查看以上代码是否可以重构如下:

X *xPtr = 0;
class Z 
{   
    // only refer to xPtr when mycond is true.    
    public int func(boolean mycond) 
    {
        //same random operations;                 

        if(mycond)  
        {        
            xPtr = new X(5,7);       
            xPtr.func();      
        }
    }

   // and don't forget delete xPtr;
} 

答案 5 :(得分:0)

你的要求就是不重复某些事情,你可以使用空对象模式。

class Base
{
};
class X : public Base
{
};
class NullX : public Base
{
};

然后

int funX(boolean mycond) { 
    Base* p = NULL;
    if (mycond)
       p = new x(5,7);
    else
       p = new NullX;
    //... some other 

    //if (mycond) 
    p->func();
} 

然后我们可以删除第二个if语句。

而且,如果你的条件仅用于控制X,那么funX将是:

int funX (Base& x)
{
   //some other
   x.func();
}

并且mycondtion将是另一个函数,

Base* getBase(int mycond)
{
   if (mycond)
     return new X(5, 7);
   return new NullX;
}

然后该函数将被完全重构。