2012-09-13 2 views
2

나는 생성자에서 객체 생성을 수행하는 것이 좋지 않은 스타일이라고 읽었습니다 ... 그러나 왜 나쁜 스타일로 간주되었는지 잊었습니다 (특히 의존성 주입을 사용할 때). 당신이 조롱 - 멀리 할 수 ​​있기 때문에 MyMemberFactory을생성자의 객체 생성

Myclass 
{ 
    Myclass(MyMemberFactory& fac) 
    { 
     for(Some criteria) 
      push_back(fac.createMyMemberType()); 
    } 

    vector<MyMemberType*> getMyMember(); 
    { 
     return myMember_; 
    } 
    ... 

private: 
    vector<MyMemberType*> myMember_; 
} 

그래서 당신은 문제없이 단위 테스트를 사용할 수 있습니다 여기에

의사 코드로 생성자에서 객체 생성의 예

. for 루프를 별도의 initialize-method로 옮기면 이중 초기화를 확인하는 데 필요하며 초기화가 이미 완료된 경우 모든 getters가 먼저 ckeck해야합니다. 여기에 별도의 초기화 사용하여 코드 : 나는 첫 번째 방법을 통해 두 번째 방법을 사용해야하는 이유

Myclass 
{ 
    Myclass() : isInitialized_(false) 
    { 

    } 

    void initialize(MyMemberFactory& fac); 
    { 
     if(isInitialized_) 
      throw "Error: Double-Init is not permitted."; 

     for(Some criteria) 
      push_back(fac.createMyMemberType()); 

     isInitialized_ =true; 
    } 

    vector<MyMemberType*> getMyMember(); 
    { 
     if(isInitialized_) 
      throw "Initialize first!"; 

     return myMember_; 
    } 
    ... 

private: 
    vector<MyMemberType*> myMember_; 
    bool isInitialized_; 
} 

그래서, 어떤 이유를 알고 있습니까? 아니면 어쩌면 방금 잘못 생각한 것일 수도 있습니다. 첫 번째 접근법은 완벽하게 괜찮습니까?

답변

2

첫 번째 방법은 실제로 좋습니다. 생성자에서 객체 생성이 문제가되는 것은 아닙니다. 생성자을 사용하면 문제가 발생합니다. 따라서

Myclass() 
{ 
    MyMemberFactory fac; 
    for(Some criteria) 
     push_back(fac.createMyMemberType()); 
} 

클라이언트가 더 이상 다른 테스트 팩토리 (예 : 테스트)를 사용할 수 없기 때문에 문제가 될 수 있습니다.

+0

알았어, 고마워 ... 나는 방금 너무 일반적인 방식으로 내 마음 속에서 제한을 받았다. – Alex

3

생성자가 예외를 throw하면 소멸자가 호출되지 않으므로 수동으로 할당 한 모든 메모리가 손실됩니다.

+1

두 번째 변형에서 'isInitialized_'는 '초기화'가 끝나면 true로 설정되기 때문에 동일합니다. 두 번째 버전은 첫 번째 버전보다 낫지 않습니다. 진정한 해결책은 (예외 처리가 필요하다면) 우선 원시 포인터 벡터를 가지지 않기 위해서입니다. –

+0

@Frerich, 네, 두 번째 버전은 좋지 않습니다. 이것은 내가 생각할 수있는 유일한 _big_ 이유입니다. – SingerOfTheFall

+0

좋은 지적 .. 실제로 실제 코드에서 멤버에 대한 자동 포인터를 사용합니다. 질문을 단순화하기 위해 제거했습니다. – Alex