2009-07-06 3 views
2

구성에서 다른 클래스의 생성을 제어 할 수 있습니까?구성으로 제어 가능한 다른 클래스를 만들 수 있습니까?

BaseClass* getClassObject(int type) 
{ 
    switch (type) 
    { 
    case 1: 
     return new DerivedClass1(); 
    case 2: 
     return new DerivedClass2(); 
    default: 
     return 0; 
    } 
} 

는 사용자가 바로 데이터를 입력 할 필요가 있도록 데이터 구조의 일종으로 제어를 전송할 수 있습니다 :

말, 나는 하드 코딩되는이 작업을 수행하는 기능을 가지고 함수가 동작하는 방식을 제어하는 ​​구조체?

+1

혹시 조금 질문을 명확히 할 수 있습니다. switch 문에 어떤 문제가 있습니까? 컴파일 타임에 타입을 알아야한다는 사실? 정수 (클래스 이름을 가진 문자열)와 다른 것을 전달하고 싶습니까? –

답변

0

저는 C++ 전문가가 아닙니다. 저는 Delphi/C# 배경에서 왔습니다. Delphi 나 C#에서는 리플렉션을 사용하여 가능한 클래스 목록을 동적으로 생성 한 다음 일부 구성 파일에 구성된 클래스를 선택했습니다. 그러나 이것이 C++에서도 가능한지 확실하지 않습니다.

+0

C++은 여러분이 말하는 종류의 리플렉션을 지원하지 않습니다. –

+0

그럼 수치 스럽네요 ;-) 유용한 대답 목록에서 제 대답을 찾으세요. –

+0

또는 표시된 것을 시작하기 전에 삭제할 수 있습니다;) –

1

C++에서 컴파일시 모든 유형의 이름을 알아야합니다. 사용자가 런타임에 클래스를 생성하도록 허용 할 수 없습니다. 그러나 게시 된 함수는 작동 할 것입니다 - 구성 파일에는 DerivedClass1 또는 DerivedClass2를 생성 할 정수가 포함됩니다. 이것은 읽고 스위치를 수행하는 데 사용됩니다.

+0

네, 맞습니다. 값 "type"자체는 구성 데이터 구조/파일에서 파생 될 수 있습니다. – Andy

1

유용한 정보는 Factory method pattern입니다.

+0

어, 내 질문에 함수는 공장 패턴입니다! 모든 것을 구체적으로 적어 두지 않는 방법이 있는지 확인하려고합니다. – Andy

+0

공장 패턴처럼 보였습니다. 그 링크를 게시 한 이유입니다. 그 패턴이 너에게 친숙한 지 모르겠다. –

+0

걱정마. 지금 무슨 뜻인지 알기를 바랍니다. – Andy

2

Neil은 C++에서 언급 했으므로 런타임에 클래스를 만들 수 없습니다.

질문을 올바르게 이해하지 못했지만 기능/개체가 사용자가 제공 한 데이터에서 다르게 동작하게하려면 필요에 따라 다음 중 하나를 시도해보십시오.

1] 코드에서 언급 한 바와 같이 당신이

또는

2] 당신은 공장 패턴을 사용할 수 있습니다이 필요 만들 수있는 하나 스위치 나 조건문을 사용할 수 있습니다 (사용자가 제공 한 데이터에 다른 기능을 작동하기 위해) 니펫을 오브젝트 유형

또는

3] 당신이 사용할 수있는 빗 (사용자가 데이터를 제공에 따라이 객체가 다른 동작을 생성하는 코드로 교체 될 수있는 공통 기본 클래스를 가질 수 있습니다, 다른 객체를 만들려면) a) 작성자 함수 b) 상속 및 인터페이스 c) 및 동적 라이브러리 로딩 을 사용하여 런타임에 적절한 유형의 객체를 만들고로드하십시오. (주어진 사용자 데이터에 따라 런타임에 특정 객체 또는 함수 만로드)

+0

답장을 보내 주셔서 감사합니다. 나는 런타임에 수업을 발명하는 것에 관심이 없다. 코드를 더 편집 가능하게 만드는 방법에 관심이 있습니다 (코드는 실존 가능한 클래스에서만 작동합니다). – Andy

+0

또 다른 방법은 c/C++와 함께 스크립팅 기능을 사용하는 것입니다. 스크립팅을 포함하기 위해 필요한 노력이 이점을 정당화하거나 과장 될 것이라는 확신이 들지는 않습니다. 1] TCL과 같은 언어를 c/C++와 함께 사용할 수 있습니다.이 언어는 C와 거의 함께 사용할 수 있습니다. 또는 2] 제한된 기능의 스크립트 언어를 만들 수 있습니다. 첫 번째 방법은 TCL에 대한 외부 종속성을 만들지 만 파서와 제어문을 제공하지 않도록합니다. 제한된 기능이 필요하고 향후에 많은 확장이 필요하지 않을 때까지 둘째로 좋습니다. – nurxb01

1

질문에 제공된 제한된 정보에서 C++ 종속성 주입을 읽고 고려하는 것이 좋습니다 컨테이너.

귀하의 요구 사항에 따라 약간 무거울 수 있지만 질문에서 알기가 어렵습니다. FYI, Dependency injection (http://martinfowler.com/articles/injection.html)은 마틴 파울러 (Martin Fowler)가 작성한 용어로 Inversion of Control (좀 더 구체적으로 두 주제를 다룰 예정 임)입니다.

개인적으로 구성 파일을 통해 요청 된 개체의 런타임 구성을 가능하게하는 C#/.NET 종속성 주입 컨테이너 인 Castle Windsor와 함께 작업했습니다.

Wikipedia (http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks)에 C++ 종속성 주입 컨테이너 목록이 있습니다. C++을 수행 한 지 몇 년이 지났기 때문에 더 많은 것을 말할 수는 없습니다.

1

또 다른 대안은 BaseClass에 대한 인터페이스의 일부가 clone() 기능인 프로토 타입 패턴을 사용하는 것입니다. 그런 다음 프로토 타입 인스턴스의 배열을 만들고 복제본을 호출하여 새 객체를 가져옵니다. 이는 값이 다른 인스턴스와 비헤이비어가 다른 인스턴스를 작성하려는 경우 유용하며 팩토리 메소드를 작성하는 것보다 작업이 적을 수 있습니다.

class BaseClass 
{ 
public: 
    virtual BaseClass* clone() const = 0; 
    virtual ~BaseClass() { } 
    virtual void write() const = 0; 
}; 

template <class C> 
class Cloneable : public BaseClass 
{ 
public: 
    virtual BaseClass* clone() const { 
     return new C (*static_cast<const C*> (this)); 
    } 
}; 

class TypeA : public Cloneable<TypeA> 
{ 
    int value; 

public: 
    TypeA (int value) : value (value) { } 

    virtual void write() const { 
     std::cout << "TypeA (" << value << ") @ " << (void*) this << std::endl; 
    } 
}; 

class TypeB : public Cloneable<TypeB> 
{ 
public: 
    TypeB() { } 

    virtual void write() const { 
     std::cout << "TypeB @ " << (void*) this << std::endl; 
    } 
}; 



int main (int argc, char* argv[]) 
{ 
    std::vector<BaseClass*> prototypes; 

    prototypes.push_back (new TypeA (1)); 
    prototypes.push_back (new TypeA (2)); 
    prototypes.push_back (new TypeB); 

    // create some objects 
    std::vector<BaseClass*> instances; 

    for (size_t i (0); i < 8; ++i) 
     instances.push_back (prototypes [ i % 3 ] -> clone()); 

    for (size_t i (0); i < 8; ++i) 
     instances[ i ] -> write(); 

    // todo: delete everything 
}