为什么我不能在继承树中静态_cast 模板化对象?

iag*_*ito 2 c++ inheritance templates casting

简而言之:

  • Derived 继承自 Base
  • Holder 模板化为包含指向任何内容的指针
  • 我可以说一个对象知道Holder<Base>是一个Holder<Derived>.

    我怎么能告诉我的编译器?

这不编译:

struct Base { };

struct Derived : Base { };

template <typename T>
struct Holder {
    T* point;
    int id;
};

Derived* d = new Derived();
Holder<Base> holder {d, 12};
Holder<Derived> specific( static_cast<Holder<Derived>>(holder) );
Run Code Online (Sandbox Code Playgroud)

error: no matching conversion for static_cast from 'Holder<Base>' to 'Holder<Derived>'

这肯定是天真的尝试。但是为什么这不起作用,我应该如何获得specific我需要的持有人?

Jon*_*ely 5

因为Holder<Derived>不是从 派生的Holder<Base>,所以它们是完全不相关的类型,恰好是从同一个类模板生成的。

您可以创建一个Holder<Derived>包含正确值的:

Holder<Derived> specific{ static_cast<Derived*>(holder.point), holder.id };
Run Code Online (Sandbox Code Playgroud)

或者您可以Holder通过添加执行转换的转换构造函数来将该功能添加到类模板本身:

template <typename T>
struct Holder {
    Holder(T* pt, int id) : point(pt), id(id) { }

    template<typename U>
        Holder(const Holder<U>& h)
        : point(static_cast<T*>(h.point)), id(h.id)
        { }

    T* point;
    int id;
};
Run Code Online (Sandbox Code Playgroud)

现在您最初的使用尝试static_cast将起作用,因为它们之间存在有效的转换,或者您可以将其写为:

Holder<Derived> specific( holder );
Run Code Online (Sandbox Code Playgroud)

只要编译,该语句就会编译static_cast<Derived*>(holder.point)