Are there practical uses for dynamic-casting to void pointer?

后端 未结 7 1279
隐瞒了意图╮
隐瞒了意图╮ 2020-11-27 14:00

In C++, the T q = dynamic_cast(p); construction performs a runtime cast of a pointer p to some other pointer type T that must

7条回答
  •  庸人自扰
    2020-11-27 14:50

    This might be one way to provide an Opaque Pointer through an ABI. Opaque Pointers -- and, more generally, Opaque Data Types -- are used to pass objects and other resources around between library code and client code in such a way that the client code can be isolated from the implementation details of the library. There are other ways to accomplish this, to be sure, and maybe some of them would be better for a particular use case.

    Windows makes a lot of use of Opaque Pointers in its API. HANDLE is, I believe, generally an opaque pointer to the actual resource you have a HANDLE to, for example. HANDLEs can be Kernel Objects like files, GDI objects, and all sorts of User Objects of various kinds -- all of which must be vastly different in implementation, but all are returned as a HANDLE to the user.

    #include 
    #include 
    #include 
    using namespace std;
    
    
    /*** LIBRARY.H ***/
    namespace lib
    {
        typedef void* MYHANDLE;
    
        void        ShowObject(MYHANDLE h);
        MYHANDLE    CreateObject();
        void        DestroyObject(MYHANDLE);
    };
    
    /*** CLIENT CODE ***/
    int main()
    {
        for( int i = 0; i < 25; ++i )
        {
            cout << "[" << setw(2) << i << "] :";
            lib::MYHANDLE h = lib::CreateObject();
            lib::ShowObject(h);
            lib::DestroyObject(h);
            cout << "\n";
        }
    }
    
    /*** LIBRARY.CPP ***/
    namespace impl
    {
        class Base { public: virtual ~Base() { cout << "[~Base]"; } };
        class Foo   : public Base { public: virtual ~Foo() { cout << "[~Foo]"; } };
        class Bar   : public Base { public: virtual ~Bar() { cout << "[~Bar]"; } };
    };
    
    lib::MYHANDLE lib::CreateObject()
    {
        static bool init = false;
        if( !init )
        {
            srand((unsigned)time(0));
            init = true;
        }
    
        if( rand() % 2 )
            return static_cast(new impl::Foo);
        else
            return static_cast(new impl::Bar);
    }
    
    void lib::DestroyObject(lib::MYHANDLE h)
    {
        delete static_cast(h);
    }
    
    void lib::ShowObject(lib::MYHANDLE h)
    {
        impl::Foo* foo = dynamic_cast(static_cast(h));
        impl::Bar* bar = dynamic_cast(static_cast(h));
    
        if( foo ) 
            cout << "FOO";
        if( bar )
            cout << "BAR";
    }
    

提交回复
热议问题