2011-03-06 2 views
3

나는 C++에서 그 이름의 클래스 객체를 생성하기 위해 파일에서 읽어 들인 텍스트 값을 사용할 수 있는지 궁금합니다.텍스트 파일에 제공된 클래스 이름을 기반으로 개체를 만드시겠습니까?

contents of file: "MyClass" 
code: read file 
code: instantiate "MyClass" object. 

가능한 경우 if/then/elses 전체 하드 코드를 피하고 싶습니다. 죄송합니다. 기술적 인 측면에서이 문제를 설명하는 방법을 모르겠습니다.

+1

... 내 지식으로는 불가능합니다. 너 그런 식으로 원하는 이유가 뭐야? – quasiverse

+0

음 ... 괜찮은 것 같아 보이지 않는 것 같습니다. 비용을 계산할 때 프로그램에서 사용하게 될 설정 파일에 비용 기능을 지정하고 싶었습니다. –

+0

파일에서 실제 코드를 원한다면 내 대답을 무시하십시오. 그것은 참으로 가꾼이 아닙니다. – Jollymorphic

답변

0

대부분의 C++ 프레임 워크 (예 : MFC, 부스트)는 일종의 객체 직렬화를 지원하지만 일반적으로 사람이 읽을 수있는 텍스트 파일 형식을 사용하지는 않습니다. C++에서 인스턴스가 파일에 기록되는 모든 클래스 유형은 해당 프로그램이 이러한 파일을 쓰거나 읽을 수 있도록 (즉, 컴파일 및 링크 된) 파일에 있어야합니다 (예 : 컴파일 및 링크).

0

C++과 같은 컴파일 된 언어를 사용하면 그렇게 할 수 없습니다. 이러한 것들은 PHP와 같은 인터프리터 언어에서만 가능합니다.

8

몇 가지 제한 사항을 신경 쓰지 않는 한 매우 쉽습니다. 작업을 수행하는 가장 쉬운 방법은 하나의 공통 기본 클래스에서 비롯된 클래스로 제한합니다. 이 경우에, 당신은 같은 것을 할 수 있습니다

struct eval_x : functor_base { 
    virtual bool operator()() { std::cout << "eval_x"; } 
}; 

struct eval_y : functor_base { 
    virtual bool operator()() { std::cout << "eval_y"; } 
}; 

그런 다음 우리는 각각의 객체를 생성 할 수있는 방법이 필요합니다 :

// warning: I've done this before, but none of this code is tested. The idea 
// of the code works, but this probably has at least a few typos and such. 
struct functor_base { 
    virtual bool operator()() = 0; 
}; 

당신은 분명히 그 염기로부터 유도 된 몇 가지 구체적인 클래스가 필요합니다 유형 : 마지막으로

functor_base *create_eval_x() { return new eval_x; } 
functor_base *create_eval_y() { return new eval_y; } 

, 우리는 공장 기능에 이름과지도가 필요합니다

일반적인 주제에 많은 변화가 물론있다

char *name = "eval_x"; 

// the map holds pointers to functions, so we need to invoke what it returns 
// to get a pointer to a functor: 
functor_base *b = name_mapper.find(name)(); 

// now we can execute the functor: 
(*b)(); 

// since the object was created dynamically, we need to delete it when we're done: 
delete b; 

: 우리는 함수 객체에 이름에서 매핑 할 수 있도록 (! 마지막으로) 충분히 우리를 준다

. 예를 들어, 오브젝트를 동적으로 작성하는 팩토리 함수 대신에 정적으로 각 오브젝트의 인스턴스를 작성하고 정적 오브젝트의 주소를 맵에 넣을 수 있습니다.

+0

... 나는 똑같은 이유로 영리함을 위해서 이것을 업 워드 (upvote)할지 또는 다운 vote 할지를 잠시 동안 결정할 수 없었다. :-) – ceo

+0

@ceo : Hmmm .. 나는 특히 "영리한"것이라고 생각하지 않았습니다. 이름에서 기능으로 매핑하는 데 꽤 일반적인 데이터 구조를 간단히 적용했습니다. 통역사와 같은 것을 작성하는 데에는 모두 매우 일반적입니다. 이는 제한된 형태의 통역사 인 것 같습니다. –

1

이렇게하려면 추상 팩토리를 사용할 수 있습니다. 제한 사항은 클래스가 기본 클래스를 구현해야하므로 추상 팩토리에 팩토리 클래스를 등록해야합니다.

class AbstractFactory; 
class Factory; 
class Object; 

// base marker class for all the classes that need this instantiation strategy 
class Object{} 

class Factory 
{ 
public: 
    //override this in concrete factories 
    virtual Object* create() = 0; 
}; 
// helper macro to declare an inner class that's a default factory 
#define DECL_DEFAULT_FACTORY(ObjectClass) class Factory : public Factory \ 
{\ 
public:\ 
    Factory(){}\ 
    virtual ~Factory(){}\ 
    Object* create(){ return new ObjectClass(); } \ 
} 
// this can be made a singleton 
class AbstractFactory 
{ 
public: 
    void registerClass(const String& clsName, Factory* factory){ //put this in a std::map } 
    void deregisterClass(const String& className){ //remove factory from map and delete the ptr } 
    Object* create(const String& className) 
    { 
    Factory* factory = factories[className]; 
    if(factory){ return factory->create(); } 
    else{ return 0; } 
    } 
}; 
그래서

그것은처럼 사용한다 : 다른 곳에서 당신이

abstractFactoryInstance->registerClass("SampleClass",new SampleClass::Factory()); 

할 필요가 다음 AbstractFactory는

SampleClass* obj = (SampleClass*)(abstractFactoryInstance->create("SampleClass")); 

당신을 할 준비가되어

class SampleClass : public Object 
{ 
//impl goes here 
DECL_DEFAULT_FACTORY(SampleClass); 
} 

및 체계를 더 구체화 할 수있다. 공장 템플릿 클래스 선언으로

관련 문제