从包装器接口动态转换

时间:2013-02-24 17:16:11

标签: c++ templates casting

在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>()
如果dynamic_cast_to()确实SomeDerived继承SomeBase,则{p> NULL会返回指针,如果不是dynamic_cast,则返回指针{/ p>}。

这甚至可能吗?

3 个答案:

答案 0 :(得分:1)

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

我很惊讶问题是如何实现dynamic_cast_to功能。

如何避免考虑标准dynamic_cast呢?

答案 1 :(得分:1)

我不认为这可以针对任意类型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; }
};

答案 2 :(得分:0)

不可能,因为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;
}