来自包装器接口的动态强制转换

dynamic cast from a wrapper interface

本文关键字:动态 转换 接口 包装      更新时间:2023-10-16

在C++中,我希望能够执行以下操作:

struct IWrapper {
    template<typename U>
    U* dynamic_cast_to() { ??? } // what to do here?
};
template<typename T>
struct Wrapper : IWrapper {
    Wrapper(T* _p) :p(_p) {}    
    T* p;
};

有了这个,我想能够做

SomeDerived *a = new SomeDerived;
IWrapper *x = new Wrapper<SomeDerived>(a);
SomeBase *b = x->dynamic_cast_to<SomeBase>()

如果SomeDerived确实继承了SomeBase,那么dynamic_cast_to()应该返回一个指针,如果不是,则NULL应该返回指针,这与普通dynamic_cast的工作方式相同。

这可能吗?

IWrapper一个虚拟析构函数并使用dynamic_cast

我很惊讶有人问我如何实现dynamic_cast_to函数。

那么如何避免考虑标准dynamic_cast呢?

我认为这不能用于任意类型的t和U。原因是编译器必须在编译时为特定类型对生成dynamic_cast代码,并且不存在在编译时同时已知这两种类型的地方。

如果你可以限制IWrapper只适用于从某个具有虚拟成员功能的基础派生的类型,那么它可以这样工作:

struct IWrapper {
    template<typename U>
    U* dynamic_cast_to() { return dynamic_cast<U*>(commonBasePtr()); }
    virtual CommonBase* commonBasePtr() = 0;
};
template<typename T>
struct Wrapper : IWrapper {
    Wrapper(T* _p) :p(_p) {}    
    T* p;
    virtual CommonBase* commonBasePtr() { return p; }
};

这是不可能的,因为IWrapper对t一无所知,也无法访问指针。这应该有效:

template <typename T>
struct IWrapper {
    IWrapper(T* p) : p_(p) {}
    template<typename U>
    U* dynamic_cast_to() { return dynamic_cast<U*>(p_); }
private:
    T* p_;
};
template<typename T>
struct Wrapper : IWrapper<T> {
    Wrapper(T* _p) : IWrapper<T>(_p), p(_p) {}    
    T* p;
};
struct SomeBase {
    int a;
};
struct SomeDerived : public SomeBase {
    int b;
};
int main()
{
    SomeDerived *a = new SomeDerived;
    IWrapper<SomeDerived> *x = new Wrapper<SomeDerived>(a);
    SomeBase *b = x->dynamic_cast_to<SomeBase>();
    return b->a;
}