2009-10-08 5 views
5

C++에서 C# typeof-command 비헤이비어를 시뮬레이트하는 방법?C++에서 typeof하는 방법

C# 예제 :

public static PluginNodeList GetPlugins (Type type) 
{ 
... 
} 

전화 :

PluginManager.GetPlugins (typeof(IPlugin)) 

방법이 사용 C를 구현하는 ++? 어쩌면 QT 또는 Boost 라이브러리가 해결책을 제공할까요?

.GetPlugins (...)을 파일 (.so 또는 .dll)에서 이러한 종류의 개체를로드하는 방식으로 구현하려면 어떻게해야합니까?

+0

무엇 내 질문의 두 번째 부분에 대해. 나에게 그것은 내가 가장 직면하는 문제 중 하나이다. 누군가가 올바른 방향으로 나를 가리킬 수 있다면 매우 높이 평가 될 것입니다. –

답변

2

완전한 형식새와 같은 동작을 원하면 RTTI (run-time type information)을 사용해야합니다. 많은 컴파일러에서 런타임 오버 헤드가 발생하므로 RTTI 사용을 명시 적으로 활성화해야합니다.

그런 다음 typeid 또는 dynamic_cast을 사용하여 개체 유형을 찾을 수 있습니다.

typeid를 사용하지 않으려면 상속, 포인터 및/또는 오버로드를 사용해야합니다. 부스트 당신을 도울 수 있지만 너무 어렵지 않아.

예 1 :

class Iplugin { ... } 

class Plugin1 : public Iplugin { ... } 
class Plugin2 : public Iplugin { ... } 

void getplugins(Iplugin* p) { 
    // ... you don't know the type, but you know 
    // what operations it supports via Iplugin 
} 

void getplugins(Plugin1& p) { 
    // expliticly handle Plugin1 objects 
} 

당신은 RTTI와 유형 ID의 사용을 피하는 몇 가지 방법이있다 볼 수 있듯이. 아래 그림과 같이

+1

캐스팅이 vtable을 가진 클래스보다 중요합니다 - RTTI는 dynamic_cast를 수행하는 데 의존합니다. – fbrereto

+1

RTTI에 런타임 오버 헤드가 발생한다고 생각하지 않습니다. 클래스 별 추가 정보를 vtable에 저장해야하므로 생성 된 코드가 약간 더 커집니다. 언급 한 바와 같이 클래스에는 vtable이 있어야합니다. 이러한 클래스에는 거의 항상 가상 소멸자 (vtable을 보장)가 있어야합니다. – TrayMan

+1

간접적으로 코드 크기가 크기 때문에 런타임 오버 헤드가 발생할 수 있습니다. – rlbond

8

당신은 유형을 테스트 dynamic_cast는을 사용할 수

IPlugin* iPluginPtr = NULL; 
iPluginPtr = dynamic_cast<IPlugin*>(somePluginPtr); 

if (iPluginPtr) { 
    // Cast succeeded 
} else { 
    // Cast failed 
} 
+2

이 기능을 사용하려면 RTTI를 활성화해야합니다. – csl

+13

그렇습니다. 즉, 언어는 C++이어야합니다. 표준 C++에는 RTTI가 포함됩니다. 컴파일러가 그것을 끄도록 허락한다는 사실은 관련이 없어야합니다. 이렇게하면 비표준 동작이됩니다. 언어의 일부를 사용하지 않으려면 * 당연히 코드에 의존하는 * 코드가 작동하지 않습니다. 코드가 Fortran이나 C가 아닌 C++ 컴파일러에 공급되어야한다고 지적 할 수도 있습니다. – jalf

+1

@ jalf : 알았어. 컴파일러가하는 일과는 무관해야합니다. 하지만 그들은 그렇게하기 때문에 실제적으로해야 할 일을 적어 두지는 않습니다. 나는 컴파일러가 이것을 사용하여 "사용하지 않는 것에 대해 비용을 지불하지 않도록"한다고 생각합니다. – csl

5

이 동작은 RTTI (Run time type information)라고합니다. 이 기술은 피하는 것이 가장 좋지만 어떤 상황에서는 도움이 될 수 있습니다.

이 문제를 해결하는 두 가지 방법이 있습니다. 첫 번째 방법은 클래스 특정 정수 참조 코드를 반환하는 순수 가상 함수가있는 인터페이스를 작성하는 것입니다. 그런 다음이 코드를 사용하여 특정 유형을 나타낼 수 있습니다. 이러한 정수는 특정 열거 형에 저장 될 수 있습니다.

파생 클래스에서 메서드를 재정 의하여 해당 클래스 전용 형식을 반환 할 수 있습니다. 런타임 중에 예를 들어 Plugin-> getType()을 호출하면 특정 유형이 반환됩니다. 그런 다음 포인터에서 static_cast를 수행하여 파생 된 유형의 올바른 포인터를 가져올 수 있습니다.

두 번째 방법은 typeid를 사용하여 객체의 classtype을 얻는 것입니다. 그러나 이것은 컴파일러에 의존적이다. dynamic_cast를 사용하여 포인터를 캐스팅 할 수도 있습니다. dynamic_cast는 잘못된 유형으로 변환 될 때 null 포인터를 반환합니다. 정확한 유형으로 형변환 될 때 유효한 것. 동적 캐스트 메소드는 위에 설명 된 getType 메소드보다 더 큰 오버 헤드를가집니다.

+0

형식 안전 형 동적 다운 캐스팅을 수행하려면 RTTI가 필요합니다. "typeof"(GCC 확장자) 또는 "auto"/ "decltype"(C++ 0x) 기능을 제공하지 않습니다. – Adisak

2

이 문제를 해결하도록 설계하는 것이 가장 좋습니다. 객체 지향을 잘 사용하면 일반적으로 각 객체의 식별자를 저장하는 기본 클래스를 사용하여 객체 유형을 쿼리하기위한 자체 시스템을 만들 수 있습니다.

대부분의 경우 문자열 비교를 사용하여 객체 유형을 찾고 실제로 느려지므로 항상 dynamic_cast를 사용하지 마십시오.

1

부스트 유형이 있습니다. C++ 0x는 typeof를 호출하지 않지만 같은 종류의 기능을 제공하는 'auto'와 'decltype'을 모두 가지고 있습니다.

그런데, 나는이 경우에 당신이 정말로 찾고있는 것을 제공하는 사람은 아무도 없을 것이라고 확신합니다. 대부분 당신이 필요로하거나 원하는 것을 작게 만 제공합니다.

2

GCC에서 typeof()를 사용할 수 있습니다. 다른 컴파일러에서는 지원되지 않거나 템플릿을 잘못 작성하거나 버그가있는 컴파일러와 같은 "버그 기능"을 사용해야합니다 (Boost 방식처럼).

0

"C++에서 typeof()를 얻는 방법"에 직접 대답하지 않지만 C++에서 플러그인을 수행하는 방법을 찾고 있다는 질문에서 추론합니다. 그렇다면 Boost.Extension 라이브러리에 관심이있을 수 있으며 그 부분의 reflection 부분에 관심이있을 수 있습니다.

1

확실히 오버로드를 사용 하시겠습니까?

static PluginManager::GetPlugins(Type1 &x) { 
    // Do something 
} 

static PluginManager::GetPlugins(Type2 &x) { 
    // Do something else 
} 

다음 전화 :

PluginManager::GetPlugins(IPlugin);