문제

을 위해 내가 필요한 시스템을 변환하는 포인터를 오래 다음 장에 다시 포인터의 유형입니다.으로 추측할 수 있 이것은 매우 안전하지 않습니다.가 무엇을 하고 싶은 사용 dynamic_cast 변환을 수행하도록 그렇다면 내가 혼합된 그들에게 내가 null 포인터입니다.이 페이지 말 http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc05keyword_dynamic_cast.htm

Dynamic_cast 연산자가 수행 형식 변환를 수행할 필요는 없습니다.이 dynamic_cast 운영을 보장 변환하는 포인터를 기본 클래스 포인터를 파생 클래스 거나 변환 lvalue 참조 기본 클래스 참조하는 파생된 클래스입니다.A 프로그램을 사용하여 클래스 계층 구조다.이 연산자와 이 포인터를 사용 하 여 수신자를 제공 실행 시간 형식 정보(온)지원 C++.

그리고 나는 같은 오류가 발생하는 경우 null 요 그래서 동적인 내 자신의 캐스팅

template<class T, class T2> T mydynamic_cast(T2 p)
{
    assert(dynamic_cast<T>(p));
    return reinterpret_cast<T>(p);
}

와 MSVC 나는 오류"오류 C2681:'길':잘못된 표현방식에 대한 dynamic_cast".그것은 이와 함께 작동합니다 클래스는 가상 기능을...스포츠 도박에 사용되는 방법이다.내가 알고있는 지점의 캐스팅을 위/아래 주물은 상속의 문제가 아니지만 나 또한다고 생각했을 해결하는 입력 캐스팅에 문제가합니다.나는 사용할 수 있습 reinterpret_cast 만을 보장 하지 않는 동일한 유형의 안전입니다.

내가 사용해야하는지 확인하려면 내 배역은 동일 유형입니까?나는 비교할 수 있습 두 개의 포인터를 사용 하 여 수신데 때 문제가 발생하고 싶어 배역은 파생됩니다.그래서 어떻게 해결할 수 있는 이?

도움이 되었습니까?

해결책

을 해야 했 유사한 것에 적재할 때는 C++Dll 앱에서 작성된 언어에서만 지원하는 C 인터페이스입니다.여기에는 솔루션입니다 당신에게 즉각적인 오류가는 경우에는 예상치 못한 개체를 입력 전달되었습니다.이게 큰 도움이 될 수 있습을 진단하는 뭔가 잘못.

트릭은 모든 클래스는 전달하로 처리하는 상속에서 일반적인 기본 클래스입니다.

#include <stdexcept>
#include <typeinfo>
#include <string>
#include <iostream>
using namespace std;


// Any class that needs to be passed out as a handle must inherit from this class.
// Use virtual inheritance if needed in multiple inheritance situations.
class Base
{

public:
    virtual ~Base() {} // Ensure a v-table exists for RTTI/dynamic_cast to work
};


class ClassA : public Base
{

};

class ClassB : public Base
{

};

class ClassC
{
public:
    virtual ~ClassC() {}
};

// Convert a pointer to a long handle.  Always use this function
// to pass handles to outside code.  It ensures that T does derive
// from Base, and that things work properly in a multiple inheritance
// situation.
template <typename T>
long pointer_to_handle_cast(T ptr)
{
    return reinterpret_cast<long>(static_cast<Base*>(ptr));
}

// Convert a long handle back to a pointer.  This makes sure at
// compile time that T does derive from Base.  Throws an exception
// if handle is NULL, or a pointer to a non-rtti object, or a pointer
// to a class not convertable to T.
template <typename T>
T safe_handle_cast(long handle)
{
    if (handle == NULL)
        throw invalid_argument(string("Error casting null pointer to ") + (typeid(T).name()));

    Base *base = static_cast<T>(NULL); // Check at compile time that T converts to a Base *
    base = reinterpret_cast<Base *>(handle);
    T result = NULL;

    try
    {
        result = dynamic_cast<T>(base);
    }
    catch(__non_rtti_object &)
    {
        throw invalid_argument(string("Error casting non-rtti object to ") + (typeid(T).name()));
    }

    if (!result)
        throw invalid_argument(string("Error casting pointer to ") + typeid(*base).name() + " to " + (typeid(T).name()));

    return result;
}

int main()
{
    ClassA *a = new ClassA();
    ClassB *b = new ClassB();
    ClassC *c = new ClassC();
    long d = 0; 


    long ahandle = pointer_to_handle_cast(a);
    long bhandle = pointer_to_handle_cast(b);
    // long chandle = pointer_to_handle_cast(c); //Won't compile
    long chandle = reinterpret_cast<long>(c);
    // long dhandle = pointer_to_handle_cast(&d); Won't compile
    long dhandle = reinterpret_cast<long>(&d);

    // send handle to library
    //...
    // get handle back
    try
    {
        a = safe_handle_cast<ClassA *>(ahandle);
        //a = safe_handle_cast<ClassA *>(bhandle); // fails at runtime
        //a = safe_handle_cast<ClassA *>(chandle); // fails at runtime
        //a = safe_handle_cast<ClassA *>(dhandle); // fails at runtime
        //a = safe_handle_cast<ClassA *>(NULL); // fails at runtime
        //c = safe_handle_cast<ClassC *>(chandle); // Won't compile
    }
    catch (invalid_argument &ex)
    {
        cout << ex.what() << endl;
    }

    return 0;
}

다른 팁

dynamic_cast 만 사용할 수 있습니다 간의 관련 클래스를 상속입니다.변환을 위해 포인터를 오래 또는 반대로 사용할 수 있습니다 reinterpret_cast.지 여부를 확인하는 포인터가 null,당신 assert(ptr != 0).그러나,그것은 일반적으로 사용하지 않는 것이 좋습 reinterpret_cast.왜 당신은 당신이 필요로 변환하는 포인터를 오래?

또 다른 옵션은 사용하는 유니온:

union  U { 
int* i_ptr_;
long l;
}

다시 union 너무 필요한만 거.

그 기억에서 Windows64,포인터이 될 것이 64 비트 양지 long 계속 될 것이 32 비트 양 및 코드가 깨진 것입니다.적어도,당신은 선택의 정수 입력에 따라 플랫폼입니다.지 여부를 알 MSVC 에 대한 지원 uintptr_t,유형에서 제공하는 C99 을 들고 포인터를;는 것은 최고의 유형을 사용하는 경우 사용할 수 있습니다.

나머지 부분에 관해서는,다른 사람들을 해결하는 이유와 그런즉 의의 dynamic_castreinterpret_cast 충분히.

reinterpret_cast 정확한 캐스팅 여기에 사용할 수 있습니다.

이것은 꽤 많 한 것은 그것을 할 수 있습니다.

reinterpret_cast 에서 포인터를 입력하 T 형식과 다시 원래 포인터를 입력 산출한 원 포인터이다.(가 T 포인터 또는 정수형으로는 최소한 원 포인터 타입)

Note reinterpret_cast 에서 포인터를 입력하 T 이 지정되어 있지 않습니다.보장이 없는 가치에 대해의 T 형식 를 제외하고 는 경우 다음 reinterpret_cast 그것을 다시 원래 유형,당신은 원래 값입니다.그래서 가정을 하지 않도 중간 긴 값에서 당신의 경우,reinterpret_cast 완벽하게 안전하고 휴대용입니다.

편집:물론 이 도움이되지 않는 알지 못하는 경우에는 두 번째 던지,무엇을 원래의 형식이었다.는 경우에,당신은 당신입니다.긴 수 없습니다 아마도 어떤 방식으로 수행에 대한 정보를 입력 있는 포인터가 그것이 전환되었습니다.

당신이 사용할 수 있는 reinterpret_cast 을 캐스팅하는 필수적인 입력하고 다시 포인터의 유형입니다. 는 경우 필수적인 입력하기에 충분히 큰 저장소의 포인터 값을,그 변환을 변경하지 않습니다 포인터 값입니다.

으로 사람들이 이미 말,정의되지 않은 행동을 사용하 dynamic_cast 이 아닌 다형성 클래스를 제외하고(당신이 때 업캐스는 암시적으로 어쨌든 무시되 여기),그리고 그것은 또한에서만 작동합 포인터 또는 참조가 있습니다.지에 완전한 형식입니다.

당신은 더 나은 사용 ::intptr_t 에서 찾을에서 다양한 posix 시스템입니다.당신이 사용할 수 있는 형식으로의 중간 형식으로 캐스팅.

에 대한 여부를 확인 변환이 성공할 것이다,당신은 당신을 사용할 수 있습 sizeof:

BOOST_STATIC_ASSERT(sizeof(T1) >= sizeof(T2));

이 실패하는 경우에는 컴파일 시에 변환을 할 수 없습니다.거나 계속 사용 하는 조건,그리고 주장에서 실행 시간 대신 합니다.

경고: 이 당신을 방해하지 않도록 주 T* 하기 intptr_tU* U 또 다른 유형보다 T.따라서,이만을 보장 당신에게 캐스팅 변경하지 않습니다 포인터의 값을 경우 캐스팅 T* 하기 intptr_t 고 돌아 T*.(덕분에 니콜라 지을 기대할 수 있습니다 다른 보호).

당신이 원하는 무엇이 같은 소리는 정말 나쁘고 위험한 생각,그러나 당신이해야 할 그것은(즉당신이 작업에서는 기존 시스템 또는 하드웨어에서 알고 있는 것이 결코 변하지 않),다음이 포장에 있는 포인터가 어떤 종류의 간단한 구조체를 포함하는 두 회원:1)void 포인터를 객체를 인스턴스와 문자열을 열거나 일부 다른 종류의 독특한 식별자는 무엇을 말할 것이 캐스팅하는 원래 void*니다.여기서 무엇을 의미한다(참고:지 않았을 귀찮게 시험이 있을 수 있습니다 그래서 구문 오류는 그것):

struct PtrWrapper {
  void* m_theRealPointer;
  std::string m_type;
};

void YourDangerousMethod( long argument ) {

   if ( !argument ) 
     return;

   PtrWrapper& pw = *(PtrWrapper*)argument;

   assert( !pw.m_type.empty() );

   if ( pw.m_type == "ClassA" ) {
     ClassA* a = (ClassA*)pw.m_theRealPointer;
     a->DoSomething();
   } else if (...) { ... }

}

dynamic_cast<> 이 캐스트 사용하기 위한 것에 종(에서 다형 감).을 강제로 주의 pointerlong (litb 올바르게 제안하지 말고 static_assert 의 호환성을 보장한 크기)에 대한 모든 정보 유형의 포인터 을 잃게 됩니다.방법은 없을 구현하는 safe_reinterpret_cast<> 를 구하는 포인터를 백:모두 값을 입력합니다.

을 명확히 무엇을 의미:

struct a_kind {}; 
struct b_kind {}; 

void function(long ptr) 
{} 

int 
main(int argc, char *argv[]) 
{ 
    a_kind * ptr1 = new a_kind; 
    b_kind * ptr2 = new b_kind;

    function( (long)ptr1 );
    function( (long)ptr2 );

    return 0;
}

방법이 없 function() 의 종류를 확인 하려면 포인터를 통과하고"아래"캐스팅을 적절한 입력하지 않는 한,어느:

  • 긴 감싸고 있는 개체는 일부의 정보 유형입니다.
  • 유형을 자체에서 인코딩된 참조된 객체입니다.

모두 솔루션은 추 피해야 하므온은니다.

또한,더 나은 사용 size_t 대의 긴-내 생각이 유형은 보장하는 호환되의 크기와 주소 공간이 있습니다.

한 빨리 당신이 결정하는 캐스팅에 대한 포인터 길이,당신이 던진 유형을 안전하다.

dynamic_cast 사용하여 캐스팅 up&down 유도 나무입니다.즉,기본 클래스에서 포인터 파생된 클래스가 포인터이다.이 있는 경우:

class Base
{
};

class Foo : public  Base
{
};

class Bar : public Base
{
};

당신이 사용할 수 있습 dynamic_cast 에서 이 방법...

Base* obj = new Bar;

Bar* bar = dynamic_cast<Bar*>(obj); // this returns a pointer to the derived type because obj actually is a 'Bar' object
assert( bar != 0 );

Foo* foo = dynamic_cast<Foo*>(obj);  // this returns NULL because obj isn't a Foo
assert( foo == 0 );

...그러나 사용할 수 없습니다 동적으로 캐스팅 주조에 밖으로 유도 나무입니다.당신이 필요 reinterpret_cast 또는 C 스타일의 캐스팅합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top