【发布时间】:2015-04-01 19:40:14
【问题描述】:
我有一个继承自模板定义类型的类型。模板定义的类型保证具有给定的基类。我想要做的是能够进行 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]);
【问题讨论】:
-
衍生
!=衍生 。它们是完全不同的类型,因此 dcast2 正确设置为 null。解决这个问题的一种方法是让 Derived 从另一个类继承,比如说 DerivedBase,然后动态转换为该类。 -
你有点混合了两个不同的概念:运行时多态性和编译时多态性。你可以按照 Creris 的建议去做,或者考虑重构你的代码以避免比较不同的模板类型
-
Derived
和 Derived 并不是完全不同的类型,因为它们最终都继承自 Base。也就是说,我可以成功地将它们中的任何一个转换为 Base*。我并不是说演员阵容是错误的,只是说明了我希望从一些可能的解决方案中得到什么。事实上,这是编译时保证的混合,两者都继承自 Base 并且都具有由 Derived 定义的相同接口,我希望在运行时利用这些接口。在这里使用建议的 DerivedBase 是一个简单的解决方案,最终解决了我想要的 90% 的问题。
标签: c++ templates generic-programming