2009-12-23 5 views
5

나는이 클래스에서 메서드을 실행할 방법 void run(string method)을 갖기 위해 노력하고 있습니다. 예를 들어 :이름 만 주어진 메소드를 어떻게 호출 할 수 있습니까?

class Foo { 
    public: 
    void run(string method) { 
     // this method calls method *method* from this class 
    } 
    void bar() { 
     printf("Function bar\n"); 
    } 
    void foo2() { 
     printf("Function foo2\n"); 
    } 
} 

Foo foo; 

int main(void) { 
    foo.run("bar"); 
    foo.run("foo2"); 
} 

이 인쇄 것입니다 :

Function bar 
Function foo2 

감사합니다! :)

+1

당신이 달성하려고하는 무엇을? –

답변

15

호출하려는 모든 함수가 동일한 서명을 가지고있는 한 문자열을 멤버 함수 포인터에 매핑하는 std::map을 만들 수 있습니다.

std::map<std::string, void(Foo::*)()> function_map; 
+2

그렇지 않으면 {if() {} else if() {else {}'가 여전히 여기에 있습니다 ;-) –

+2

만약이 솔루션을 사용한다면 정적이 될 것입니다. 지도 - 컴파일 타임에 할 수있는 것을 런타임까지 연기하지 마십시오. –

2

당신은 함수의 이름 인지도의 키, 멤버 함수 포인터의지도를 만들 수 있습니다

지도

처럼 선언 될 것이다. 멤버 함수에 대한 포인터는 약간 어렵다.

http://www.parashift.com/c++-faq-lite/pointers-to-members.html

더 쉬운 방법은 적절한 함수를 호출하여 run 기능의 경우 - 당시 다른 블록의 무리를하는 것입니다.

6

이미 언급 한지도 솔루션은 고정 함수 목록에서 작동하지만 일반적으로 C++에서 이와 같이 인트로 스펙 션하는 방법은 없다고 생각합니다. 즉, "methodName이라는 메서드가 있습니까? 그렇다면 호출하십시오."라는 함수 void perform(string methodName)을 사용할 수 없습니다.

+0

예, C++은 Java와 전혀 관련이 없습니다. – Omnifarious

+0

... Objective-C, Python, Perl, JavaScript, Ruby, C#을 좋아하지 않습니다. – benzado

+0

@benzado : Objective-C는 메시지를 보내는 것과 완전히 다릅니다. 객체가 메시지에 반응하는 방법을 알고 있으면 코드를 실행합니다. Python/Perl/Javascript : 모든 객체는 단지지도이므로 메서드는 값으로 연결된 객체입니다. C#과 Java는 서로 다른 유형의 인트로 스펙 션 (AKA reflection)이 가능하므로 이름으로 메소드를 찾은 다음 호출 할 수 있습니다. –

1

다른 포스터에서 말했듯이 언어는 inbuilt Reflection이 없으므로 C++에서 직접이 작업을 수행해야합니다.

C# 및 Java와 같은 언어는이 기능을 내장하고 있으므로 필요에 따라 원하는 언어를 다시 생각해 볼 필요가 있습니다.

-3

RTTI 또는 일종의지도가 없으면이를 수행 할 수 없습니다. 아니면이 같은 솔루션 :

 
class Foo { 
    public: 
    void run(string method) { 
     bar(method); 
     foo2(method); 
    // ... more methods here 
    } 
    void bar(string method) { 
     if (method != "bar") return; 
     printf("Function bar\n"); 
    } 
    void foo2(string method) { 
     if (method != "foo2") return; 
     printf("Function foo2\n"); 
    } 
} 

Foo foo; 

int main(void) { 
    foo.run('bar'); 
    foo.run('foo2'); 
}

이 당신에게 다른 사람이, C++가 상자 밖으로 반사 이런 종류의 일을하지 않는 지적대로

+2

제안 된 솔루션은 간단합니다. n 메소드의 경우'run'을 호출 할 때마다 n 메소드 호출이 발생하기 때문에 비효율적입니다. 이름을 메소드에 맵핑하는 로직이 메소드들에 분산되어 있기 때문에 유지 보수가 불가능합니다. – benzado

9

를 원 같은 결과를 줄 것이다 (그리고 가능성은 있습니다 그것은 아마도 당신이하고 싶은 것이 아닙니다.)

그러나 클래스 유형과 메소드의 하위 집합에 대해이 기능을 구현하는 몇 가지 전처리 기가 있습니다. Qt의 moc은 이것의 한 예이며, 이것은 신호/슬롯 메카닉의 일부입니다. 공지 사항 method()QMetaObjectmethodCount() ...

Qt는이 테이블을 만들고 코드의 나머지 부분을에서 컴파일 빌드 프로세스에 도구를 주입하는 것입니다 수행하는 방법

. 언어 기능이 아니라 손으로 쓴 모든 것들입니다.

3

이전 답변은 해당 솔루션에 대한 것이지만 솔루션은 문제에 대해 올바른 것으로 보이지 않습니다.

두 가지 제안이 있습니다. 1) 더 나은 추상 기본 클래스를 작성하거나 2) 펑터에 기본 클래스를 사용하십시오. (함수 객체).프로세서의 명령어 세트를 시뮬레이션 프로젝트 감안할 때

, 우리는 함께 실행 시뮬레이션 할 수 있습니다 ... 더 자세히들을 살펴 보자 :

struct Instruction_Interface 
{ 
    virtual void execute(void) = 0; 
}; 

typedef std::vector<Instruction_Interface *> Instruction_Container; 

//... 
Instruction_Container::iterator iter; 
Instruction_Container program_instructions; 
//... 
for (iter = program_instructions.begin(); 
    iter != program_instructions.end(); 
    ++iter) 
{ 
    (*iter)->execute(); // Execute the instruction; 
} 

이 각 명령의 execute 방법의 호출을 할 수 있습니다를,에 관계없이의 종류의 지시. 인터페이스에 메소드를 더 추가 할 수 있습니다. 이 예에서는 명령을 텍스트로 변환하는 "toString"을 추가 할 수 있습니다.

Idea 2: Functors 

사용할 기능에 대한 기본 클래스 또는 인터페이스를 설정하십시오. 그것들을 컨테이너에 넣고 컨테이너를 반복합니다. 반복은 조건도 될 수 있습니다 요약

struct Functor_Interface 
{ 
    virtual std::string get_name(void) const = 0; 
    virtual void   execute(void) = 0; 
    virtual void   execute_if_name(const std::string& name) 
    { if (name == get_name()) 
    { 
     execute(); 
    } 
    } 
}; 

typedef std::vector<Functor_Interface *> Functor_Container; 
//... 
Functor_Container the_functors; 
//... 
Functor_Container::iterator iter; 
for (iter = the_functors.begin(); 
    iter != the_functors.end(); 
    ++iter) 
{ 
    (*iter)->execute_if_name("loader"); // Execute the functor if it is a *loader*. 
    (*iter)->execute_if_name("math"); 
} 

는,이 함수 이름을 필요로하지 않는 좋은 방법이지만, 대신 중 함수가 실행을 결정할 수 있습니다 또는 일반적으로 블라인드 실행 있는지 확인하기 위해 설계를 통해 생각 행동 양식.

1

스트레이트 C++의 경우 위의 대답이 좋습니다. 그러나 일부 툴킷 (예 : Qt)은 C++에 내성 검사를 추가 할 수 있습니다. 이것은 아마도 더 무거운 변화이며 기존 프로젝트에 대해 원하는 것이 아닌, 추가하는 툴킷/래퍼를 검색 할 가치가있는 내부 검사가 필요할 수도있는 프로젝트를 시작하는 경우입니다.

관련 문제