2017-02-16 2 views
2

기본 생성자가 삭제 된 클래스를 생각해보십시오. (실제 클래스는 훨씬 복잡하고 기본 생성자는 삭제 된 기본 생성자가있는 멤버로 인해 암시 적으로 삭제됩니다. 일부 입력 값에 따라 생성자 중 하나를 사용하여 클래스를 인스턴스화 한 다음 "많은 일"을 수행하고 싶습니다. 다음 코드는 코드 주석에 명시된 이유로이 작업을 수행 할 수없는 두 가지 방법을 보여 주지만 내가 성취하고자하는 것에 대한 아이디어를 제공합니다. 이 작업을 수행하는삭제 된 기본 생성자가있는 클래스를 조건부로 인스턴스화

#include <vector> 
class A { 
    bool m_with_v; 
    int m_i; 
    std::vector<double> m_v; 
public: 
    A() = delete; 
    A(int i) : m_i(i), m_with_v(false) {} 
    A(int i, std::vector<double> v) : m_i(i), m_v(v), m_with_v(true) {} 
    auto do_stuff() { /* do stuff depending on m_with_v */ }; 
}; 

int main(int argc, char* argv[]) 
{ 
    bool yes_no; 
    /* Obtain a value for yes_no from argv */ 

    A a; // the default constructor of "A" cannot be referenced -- it is a deleted function 
    if (yes_no) 
     a = A(1); 
    else { 
     std::vector<double> v{ 1,2,3 }; 
     a = A(1, v); 
    } 
    a.do_stuff(); 
    // do a bunch more things 

    if (yes_no) 
     A b(1); 
    else { 
     std::vector<double> v{ 1,2,3 }; 
     A b(1, v); 
    } 
    b.do_stuff(); // identifier "b" is undefined, i.e. it's gone out of scope 
    // do a bunch more things 
} 

한 가지 확실한 방법은 if 블록의 각 부분 내부의 "사물의 무리"를 이동하는 것입니다,하지만 그건 내가 피하고 싶은 중복 코드를 많이,이 발생할 것입니다.

또 다른 확실한 방법은 "여러 가지 작업"을 수행하는 함수를 만들고 if 블록의 각 부분에서 호출하는 것입니다. 그러나 특정 양의 리팩토링이 필요하며 함수 호출이 있으면 변수에 전달해야 할 많은 수의 변수가 있습니다.

내 질문은 : 조건부로 클래스를 인스턴스화하고 주변 범위에서 사용할 수있는 방법이 있습니까?

답변

2
auto a = [&]{ 
    if (yes_no) { 
     return A(1); 
    } else { 
     std::vector<double> v{ 1,2,3 }; 
     return A(1, v); 
    } 
}(); 
a.do_stuff(); 
+0

juanchopanza의 솔루션이 좀 더 간단하게 내 질문에 대답하는 동안이 솔루션을 벡터' v'는 자연스럽게 생성되지 않으며 생성자의 선택에 대해서만 생성되어야하며 주변 범위를 오염시키지 않습니다. –

4

당신은 조건 연산자를 사용하여 인스턴스화 할 수 있습니다 등등

A a = yes_no ? A(1) : A(1, {1,2,3}); 
a.do_stuff(); 

하고 있습니다.

0

자유 함수 (A ::, R에서는 정적 일 수 있습니다. Sahu는 자유 함수입니다)를 적절히 반환 할 수 있습니다.

A a = buildA(yes_no); 

buildA 등등

A buildA(bool yes_no){ 
    if (yes_no) 
     return A(1); 

하고있을 것이다.

+1

추가 로직으로 'A'를 오염시킬 필요가 없습니다. 비회원 기능으로하는 것이 좋습니다. –

0

여기서 unique_ptr<A>을 사용할 수 있습니다. 이렇게하면 실제 객체 생성을 연기하고 필요한 조건 블록 안에 적절한 인스턴스를 만들 수 있습니다. 예를 들어 :

std::unique_ptr<A> ptrA; 
if (yes_no) 
{ 
    ptrA.reset(new A(1)); 
} 
else 
{ 
    ptrA.reset(new A(1,{1,2,3})); 
} 

당신이 (C++ 14부터 사용할 수있는)를 reset 방법 대신 std::make_unique를 사용 할 수 있습니다 사용하는 C++의 실제 버전에 따라. 이 경우 ptrA = std::make_unique<A>(1);을 입력합니다.

다른 옵션은 3 진 연산자 A a = (yes_no) ? A(1) : A(1, {1, 2, 3})을 사용하는 것입니다.

다른 제안에 따라 yes_no 조건 충족 여부에 따라 if 블록에서 개체를 반환 할 수있는 별도의 함수로 개체 생성 논리를 추출하십시오.

+0

C++ 14부터'.reset (new A (args)) '대신'= make_unique (args)'를 사용하는 것을 고려합니다. –

관련 문제