2013-04-25 2 views
1

IsSame 함수에서 두 포인터가 동일한 유형의 개체를 가리키는 경우 true을 반환하고 싶습니다. 따라서 중간 통화 만 true을 반환해야합니다. D1B은 같은 것으로 간주되어서는 안됩니다.표준 안전 유형 검사?

아래의 내용은 내가 원하는 것일 뿐이지 만 표준에 따라 안전합니까?

#include <stdio.h> 

class B { virtual void foo() {} }; 
class D1 : public B { }; 
class D2 : public B { }; 
class D3 : public B { }; 

bool IsSame(B*a, B*b) { 
    if (a == 0 || b == 0) 
     return false; 
    return *(intptr_t*)a == *(intptr_t*)b; 
} 

int main() { 
    D1 d1; 
    D2 d2; 
    D1 d1b; 
    B b; 
    printf("%d %d %d\n", IsSame(&d1, &d2), IsSame(&d1, &d1b), IsSame(&d1, &b)); 
} 

는 출력 : 다음

0 1 0 
+4

코드가 의미가 없습니다. 왜 패배자인가? –

+5

'intptr_t *'로 변환 할 때주의해야 할 점은 무엇입니까? – GManNickG

+0

@GManNickG :'=='연산자가 필요합니다. 그 캐스트는 그래서 int와 같은 ptr 값을 비교할 수 있습니다. 하지만 ptr 크기는 무엇입니까 (따라서 int *가 아닌 이유) –

답변

6

두 개체의 v 테이블이 같은지 확인하려고합니다. C++ 표준은 객체의 레이아웃에있는 곳을 제외하고는 v 테이블 포인터의 존재를 말하지 않습니다. 따라서 솔루션은 일반적으로 비표준이며 프로그램의 동작은 실제로 정의되지 않습니다.

두 개의 기본 포인터가 동일한 파생 형식이지만 RTTI가 없는지 확인하려는 경우 파생 형식의 ID를 알 수있는 메커니즘이 필요합니다. 이것은 파생 된 모든 유형이 구현해야하는 ID를 반환하는 가상 메서드를 의미합니다.

+0

표준이 vtable ptr을 얻는 방법을 구체적으로 나타내지 않는 것은 수치 스럽습니다. –

+0

@ acidzombie24, user315052에서 지적했듯이, 표준은 C++ 구현이 가상 메소드를 구현하기 위해 v 테이블을 사용해야한다고 말하는 것이 아니라 가장 일반적인 메커니즘이지만이를 수행하는 유일한 방법은 아닙니다. 결과적으로 표준은 v 테이블 포인터를 얻는 방법을 지정할 수 없으며 전혀 없을 수도 있습니다. user315052에 의해 제안 된 솔루션은 아마도 가장 안전한 솔루션 일 것이고 그것은 내가하는 일일 것입니다. 너무 영리 해 지려고 노력하는 것과 같은 것이 있습니다. –

4

가 작동하는 것 같다 :

[Prompt] g++ example.cpp -std=c++11 
[Prompt] ./a.out 
d1 == d2 ? false 
d1 == d1b ? true 
d1 == b ? false 
No Template 
d1 == d2 ? false 
d1 == d1b ? true 
d1 == b ? false 

것을주의 :

#include<typeinfo> 
#include<iostream> 

class B { virtual void foo() {} }; 
class D1 : public B { }; 
class D2 : public B { }; 
class D3 : public B { }; 


template<typename T1, typename T2> 
bool is_same(const T1& t1, const T2& t2) { 
    return typeid(t1) == typeid(t2); 
} 

bool is_same_no_template(const B& b1, const B& b2) { 
    return typeid(b1) == typeid(b2); 
} 

int main(){ 
    D1 d1; 
    D2 d2; 
    D1 d1b; 
    B b; 
    std::cout<<std::boolalpha 
      <<"d1 == d2 ? "<<is_same(d1, d2)<<std::endl 
      <<"d1 == d1b ? "<<is_same(d1, d1b)<<std::endl 
      <<"d1 == b ? "<<is_same(d1, b)<<std::endl; 

    std::cout<<"No Template"<<std::endl; 

    std::cout<<std::boolalpha 
      <<"d1 == d2 ? "<<is_same_no_template(d1, d2)<<std::endl 
      <<"d1 == d1b ? "<<is_same_no_template(d1, d1b)<<std::endl 
      <<"d1 == b ? "<<is_same_no_template(d1, b)<<std::endl; 

    return 0; 
} 

는 GCC 4.7.2로 컴파일 나는 다음과 같은 출력을 얻을 결정하면이 코드는 컴파일되지 않습니다. "런타임 유형 정보"없이 컴파일 (RTTI; gcc의 -fno-rtti 컴파일 플래그).

+3

템플릿을 사용하고 있으므로'T1 '과'T2 '가 컴파일시 일치하므로'typeid '의 목적은 실제로 여기에서 손실된다. (이것이 내 대답을 삭제 한 이유입니다.) 비교할 때 질문과 일치해야하며'B *'만 있어야합니다. – GManNickG

+0

@GManNickG, @ acidzombie24 : 이해가 안되네요. (미안 해요, 초보자) 템플릿이없는 버전은 무엇입니까? 또한 'typeid'의 목적이 왜 손실되었는지 자세히 설명해 주시겠습니까? – Escualo

+0

@ acidzombie24 :이 대답과 동일한 잘못된 정보가 있었기 때문에 내 대답을 삭제했습니다.이 대답은 객체를 직접 사용하여 포인트를 놓치기 때문에 템플릿 인수에 직접 유형이 있기 때문에 해결책을 동적으로 사용하여 해결책을 보여주기 위해 개정되었습니다. 조회. – GManNickG