动态转换是否有实际用途来指向无效指针?

Ker*_* SB 72 c++ dynamic-cast

在C++中,T q = dynamic_cast<T>(p);构造执行指向p其他指针类型的指针的运行时强制转换,该指针类型T必须出现在动态类型的继承层次结构*p中才能成功.这一切都很好,很好.

但是,也可以执行,它只dynamic_cast<void*>(p)返回指向"最派生对象"的指针(参见C++ 11中的5.2.7 :: 7).我知道这个功能可能在动态转换的实现中免费提供,但它在实践中是否有用?毕竟,它的返回类型充其量void*只是,这有什么用呢?

mit*_*ull 69

dynamic_cast<void*>()确实可以使用,即使处理多重继承来检查身份.

试试这段代码:

#include <iostream>

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

class D1 : public B {
};

class D2 : public B {
};

class DD : public D1, public D2 {
};

namespace {
    bool eq(B* b1, B* b2) {
        return b1 == b2;
    }

    bool eqdc(B* b1, B *b2) {
        return dynamic_cast<void*>(b1) == dynamic_cast<void*>(b2);
    }
};

int
main() {
    DD *dd = new DD();
    D1 *d1 = dynamic_cast<D1*>(dd);
    D2 *d2 = dynamic_cast<D2*>(dd);

    std::cout << "eq: " << eq(d1, d2) << ", eqdc: " << eqdc(d1, d2) << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

eq: 0, eqdc: 1
Run Code Online (Sandbox Code Playgroud)


Ste*_*sop 7

请记住,C++允许您以旧的C方式执行操作.

假设我有一些API,我不得不通过该类型走私对象指针void*,但最终传递给它的回调将知道它的动态类型:

struct BaseClass {
    typedef void(*callback_type)(void*);
    virtual callback_type get_callback(void) = 0;
    virtual ~BaseClass() {}
};

struct ActualType: BaseClass {
    callback_type get_callback(void) { return my_callback; }

    static void my_callback(void *p) {
        ActualType *self = static_cast<ActualType*>(p);
        ...
    }
};

void register_callback(BaseClass *p) {
   // service.register_listener(p->get_callback(), p); // WRONG!
   service.register_listener(p->get_callback(), dynamic_cast<void*>(p));
}
Run Code Online (Sandbox Code Playgroud)

错的!代码是错误的,因为它在存在多重继承时失败(并且不保证在没有的情况下也能工作).

当然,API不是很C++风格,如果我继承,即使是"正确"的代码也可能出错ActualType.所以我不会声称这是一个很好的用途dynamic_cast<void*>,但它是一种用途.

  • 好吧,但是`my_callback`可以说`dynamic_cast <ActualType*>(static_cast <BaseClass*>(p))`,非?换句话说,我们可以使用`BaseClass*`作为C包装器的基础. (3认同)