2013-01-22 1 views
0

일부 멤버를 제공하는 내 애플리케이션 구성 요소의 기본 클래스가 있으며 덮어 써야하는 Init()Update() 기능이 있습니다.파생 클래스 생성자가 호출되기 전에 기본 클래스 멤버를 설정하는 방법은 무엇입니까?

class Component 
{ 
public: 
    void Set(type* Member1, type* Member2, type* Member3) 
    { 
     this->Member1 = Member1; 
     this->Member2 = Member2; 
     this->Member3 = Member3; 
    } 
    virtual void Init() = 0; 
    virtual void Update() = 0; 
    virtual ~Component() {} 
protected: 
    type* Member1; 
    type* Member2; 
    type* Member3; 
}; 

구성 요소를 운반 할 때 관리자가 있습니다. 먼저 구성 요소의 멤버를 설정 한 다음 Init()을 호출합니다. 나중에 할당 된 모든 구성 요소를 업데이트하는 데 사용할 수 있지만이 질문과 관련이 없습니다. 내가 대신 Init() 기능을 덮어 초기화 자신의 생성자를 사용하는 구성 요소를하고자하기 때문에

class Manager 
{ 
public: 
    void Add(string Name, Component* Component) 
    { 
     list[Name] = Component; 
    } 
    void Init(type* Member1, type* Member2, type* Member3) 
    { 
     for (auto i = list.begin(); i != list.end(); i++) 
     { 
      i->second->Set(Member1, Member2, Member3); 
      i->second->Init(); 
     } 
    } 
    void Update() 
    { 
     for (auto i = list.begin(); i != list.end(); i++) 
      i->second->Update(); 
    } 
private: 
    unordered_map<string, Component*> list; 
}; 

나는 내 구현 정말 행복하지 않다. 그러나 건설 시간에는 기본 클래스 멤버를 아직 사용할 수 없습니다.

파생 클래스 생성자를 통해 멤버를 전달할 수 있다는 것을 알고 있지만 특정 구성 요소가 기본 클래스의 멤버를 돌보는 것을 원하지 않습니다. 그것은 다음과 같을 것입니다. 그러나 어쨌든 저는 그것을 원하지 않습니다.

class Component 
{ 
public: 
    Component(type* Member1, type* Member2, type* Member3) 
    { 
     this->Member1 = Member1; 
     this->Member2 = Member2; 
     this->Member3 = Member3; 
    } 
    virtual void Update() = 0; 
    virtual ~Component(); 
protected: 
    type* Member1; 
    type* Member2; 
    type* Member3; 
}; 

class Specific : public Component 
{ 
public: 
    Specific(type* Member1, type* Member2, type* Member3) : Component(Member1, Member2, Member3) 
    { 

    } 
    void Update() 
    { 

    } 
}; 

그럼 파생 클래스의 생성자를 호출하기 전에 기본 클래스 멤버가 초기화되도록하려면 어떻게해야합니까?

+0

멤버 초기화 자 목록에서 파생 클래스 생성자의 본문을 입력하기 전에 기본 클래스 생성자가 호출됩니다. –

+0

"특정 구성 요소가 기본 클래스 '구성원을 돌보는 것을 원하지 않습니다. 그렇다면 왜 그들이'보호 된 '것으로 선언 했습니까? – Lundin

+0

@ Lundin. 특정 구성 요소는이를 사용해야하지만 초기화에 신경을 써서는 안됩니다. – danijar

답변

1

선택의 여지가 없습니다. 파생 클래스는 기본 클래스의 초기화 요구 사항을 알고 있거나 (기본 클래스가 해당 생성자/초기화 함수에서 정보를 필요로하기 때문에) 또는 파생 클래스의 초기화를 해당 생성자에서 이동해야합니다 (클라이언트가 기본 클래스를 초기화 한 후).

기본 클래스에서 설정해야하는 멤버 목록이 긴 경우 구조체에 모든 멤버를 패키지화하고 파생 클래스를 통해 기본 클래스로 전달할 수 있습니다.

+0

나는 지난 단락에서 설명한 타협을 좋아합니다. 어쩌면 내가 그 길로 갈거야. – danijar

0

기본 클래스 생성자가 파생 클래스 생성자보다 먼저 호출되므로 기본 클래스 생성자에 값을 설정하십시오.

+0

파생 클래스 생성자를 통해 멤버 값을 전달하여 이니셜 라이저 목록의 기본 클래스 생성자를 수동으로 호출하고 싶지 않습니다. – danijar

+0

그래서, 나는 합리적인 해결책을 찾지 못했습니다. 기본적으로, 당신이하고 싶은 것은 당신이 사용하고있는 클래스 구조의 아키텍쳐에서 작동하지 않습니다. 다른 사람이 그것을 할 수있는 영리한 방법이있을 수 있지만, 나는 그것을 모릅니다. –

0

나는 당신이 여기서 달성하기 위해 노력하고있는 것이 확실하지 않지만 몇 가지 관찰을 할 수 있습니다. 당신이 2 단계 구조를 구현하려고 시도하는 것처럼 보입니다.

먼저 기본 클래스 생성자를 사용하려면 이 있어야 파생 생성자의 값을 전달할 수 있습니다. 언어에는 다른 메커니즘이 없기 때문에 옵션이 아니라면 (또는 적어도 하나를 선택하고 싶지 않은 경우) 추가 외부 인터페이스를 사용해야합니다.

최종 질문에 대답하기 위해 기본 멤버는 이며 항상 파생 생성자가 호출되기 전에으로 초기화됩니다. 예를 들어, Update을 사용하기 전에 설정되어 있는지 확인하고 싶다고 가정합니다.

Init 함수를 호출하기 전에 Init 보호하고, 그리고 SetAndInit처럼 뭔가 Set의 이름을 변경하고 강제에 대한 설정을 항상하는 무엇. 따라서 기본 멤버가 설정되기 전에 Init으로 전화하는 것을 막을 수 있으며 비교적 유사한 인터페이스를 제공합니다.

+0

네 말이 맞아, 나는 * 초기화 * 대신에 * 세트 *를 의미했다. 마지막 단락에서 당신의 아이디어에 대해 :이 코드는 내 문제를 해결하지 못하고'Set()'이 이미 보장되기 전에'Init()'를 호출하지 않는다. – danijar