dynamic_cast 具有"Known"继承的模板类

dynamic_cast Template class with "Known" Inheritance

本文关键字:继承 Known cast 具有 dynamic      更新时间:2023-10-16

我有一个从模板定义的类型继承而来的类型。模板定义的类型保证具有给定的基类。我想做的是能够在容器中dynamic_cast或以其他方式找到与我的派生类型匹配的类型,而不考虑模板参数。

// A bunch of classes exist which inherit from Base already.
class Base{};
class Base2 : public Base {};
class BaseN : public Base {};
// Some new classes can inherit from any Base-derived class,
// but also have special attributes (i.e. function "f").
template<typename T = Base>
class Derived : public T
{
    static_assert(std::is_base_of<Base, T>::value, 
        "Class must inherit from a type derived from Base.")
    public:
        void f();
};
//
// Now process a collection of Base pointers.  
//
std::vector<Base*> objects;
// The vector may contain classes that are not "Derived".
// I only care about the ones that are.
// I want the cast here to return non-null for Derived<Base>, 
// Derived<Base2>, Derived<BaseN>, but null for Base, Base2, etc.
// This will be Null, Good.
objects.push_back(new Base)
auto dcast0 = dynamic_cast<Derived<Base>*>(objects[0]);
// This will be Non Null, Good.
objects.push_back(new Derived<Base>);
auto dcast1 = dynamic_cast<Derived<Base>*>(objects[1]);
// This will be Null, BAD! HELP!
objects.push_back(new Derived<Base2>);
auto dcast2 = dynamic_cast<Derived<Base>*>(objects[2]);

正如Creris在评论中所建议的那样,当T不是Base时,您需要一个对所有Derived<T>模板类都通用的基类。此外,对Base本身的继承应该是虚拟的,因此在实例化Derived<>时只有一个Base实例。

struct Base { virtual ~Base () = default; };
struct Base2 : virtual Base {};
struct DerivedBase : virtual Base {};
template <typename BASE = Base>
struct Derived : DerivedBase, BASE {};
    Base *b = new Derived<Base2>;
    assert(dynamic_cast<DerivedBase *>(b));

但是,您可以使用模板专门化,这样公共基类实际上就是Derived<Base>本身。

struct Base { virtual ~Base () = default };
struct Base2 : virtual Base {};
template <typename = Base> struct Derived;
template <>
struct Derived<Base> : virtual Base {};
template <typename BASE>
struct Derived : Derived<Base>, BASE {};
    Base *b = new Derived<Base2>;
    assert(dynamic_cast<Derived<> *>(b));

在线试用!