2012-01-30 4 views
0
class X { 
    X(int, int); //constructor 
    void func(); 
} 

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

이제 조건부를 기반으로 x를 초기화해야한다면 어떻게해야합니까? unaesthetic 방식으로 위의 작업을 수행하는조건부로 객체를 초기화하는 방법

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 
    } 
    } 
} 

가 나는 코드를 반복하지 않아도 더 간단하게 뭔가를 찾고 있어요.

+3

"임의 연산"후에 조건부에'x'를 선언/초기화 할 수없는 이유가 있습니까? – Mankarse

+2

정말 필요한가요? 이러한 * "임의 연산"*은 어떤 식 으로든 "x"에 의존합니까? 그렇다면, 아마도 거기에 당신이 제거하는 것이 좋을지도 모르는 부작용이있을 것입니다. 어쩌면 무작위로 수행 한 작업의 예를 들거나 전체적인 목표를 설명 할 수 있습니다. –

+0

당신은'boost :: optional'을 볼 수 있습니다. –

답변

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(); 

처럼 "임의 작업"을 고려 수, 나는 예를 위해 통과하여 참조를 사용했다.

또 다른 가능성은 이제 당신이 있는지 확인해야합니다 모든 경우에이

{ 
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. 

처럼이 사용됩니다

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(); 
    } 
} 

처럼 생성자와 소멸자의 한 쌍의 로직을 캡슐화하는 것입니다 액세스되어야하는 모든 리소스 (변수 등)는 팩 아웃 된 코드에서 사용할 수 있습니다.

다양한 선택 사이의 균형은 코드의 복잡성에 달려 있습니다. 항상 코드 판독기의 혼동을 줄이기 위해 노력하십시오. 이것은 길게 반복 된 코드 나 "숨겨진"호출 또는 다른 많은 소스에서 오는 것이므로 가능한 경우 줄여야합니다.

0

어떻게 new

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; 
} 

pointer (*)를 사용하여 위의 코드는 다음과 같은 리팩토링 할 수 있는지에 대한 :

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; 
} 
+1

포인터를 사용해야한다면,'std :: auto_ptr'와 같은 자동 포인터를 사용하십시오. – rve

+0

이 해결책은 저에게 효과적입니다. 감사! –

+0

"'public int'"는 유효하지 않습니다. C++. – Johnsyweb

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(); 
    } 
} 
+0

"'public int'"는 C++가 유효하지 않습니다. – Johnsyweb

+0

@Johnsyweb : 사실, 방공호의 예를 복사했는데 그 부분에 집중하지 않았습니다. 그것은 질문과 관련이 없습니다. – Miguel

4

제공 한 예에서는 명확하지 않습니다. R 왜 단지로 쓸 수 없습니다 :

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의 생성자는 "어떤 임의의 작업"전에 일어나야 일부 부작용이있는 경우) 경우, 당신은 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(); 
    } 
}; 

당신이 다음 비슷한 효과가 union 얻을 수있는 몇 가지 이유에 대한 boost::optional를 사용하지 않으려면 :

class Z { 
    // only refer to x when mycond is true. 
    public: 
    int func(bool mycond) { 
     union OptionalX { 
      OptionalX() {} 
      X value; 
     } x; 
     if (mycond) new (&x.value) X(5,7); 
     try { 
      //some random operations; 
      if (mycond) { 
       x.value.func(); 
       x.value.~X(); 
      } 
     } 
     catch (...) { if (mycond) x.value.~X(); } 
    } 
}; 

이것은 말하자면,이 이름은 때로는 의미가있는 범위에 이름을 도입하게됩니다. 이것은 매우 의심 스럽기 때문에 다른 디자인을 사용하는 것이 좋습니다.당신의 코드가되도록

2

확실한 대답은, 별도의 함수에서 다른 임의 작업을 넣어하는 것입니다 기능 만이 읽기 쉽고 유지 보수 할 경우 당신은 아마, 어쨌든 이렇게해야

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

.

0

귀하의 요구 사항은 단지 일부를 반복하지 않으므로 null 개체 패턴을 사용할 수 있습니다.

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; 
} 

기능을 다른 기능이있을 것 완전히 리팩토링 될 것입니다.

+0

메모리 누수가 발생하지 않는 것이 좋습니다. 그리고 포인터를 사용한다면 왜 이상한 "null 객체"를 도입하는 것이 좋을까요? –

+0

그냥 funX가 하나의 실행 흐름을 갖도록 만들고 싶습니다. – lyanbo

관련 문제