在C ++中实现基于模板的工厂时,我创建了以下allocator
函数来实例化给定的子类:
template<class ChildClass, class ParentClass>
ParentClass* allocator() {
ChildClass *child = new ChildClass();
ParentClass*parent = dynamic_cast<ParentClass*>(child);
if(NULL==parent) {
delete child;
return NULL;
}
return parent;
}
一切正常,但在通过coverity等静态代码分析工具运行代码时,delete child;
行被标记为逻辑死代码。
我进行运行时检查的原因是断言,ChildClass
派生自ParentClass
。
现在我理解,在模板扩展期间,编译器已经知道ChildClass
是否来自ParentClass
,而dynamic_cast
仅在运行时进行评估。
所以如果ChildClass
确实来自ParentClass
,那么运行时检查就是逻辑死代码(在这种情况下dynamic_cast
将始终返回non-NULL
ChildClass
已成功分配。)
但是有没有办法确保ChildClass
在编译时(模板扩展时间)从ParentClass
派生出来?
afaik,模板和继承在C ++中是无关的,但我可能会遗漏一些明显的东西。
遗憾的是,代码应该在较旧的编译器上编译(例如, Visual Studio 6 附带的C ++实现),它排除了C++11
之类的任何新扩展 - 功能
答案 0 :(得分:7)
您可以使用std::is_base_of
:
constexpr bool is_base = std::is_base_of<ParentClass, ChildClass>::value;
如果static_assert
未来自ChildClass
,则可以在ParentClass
内使用此信号来表示编译器错误。
static_assert(std::is_base_of<ParentClass, ChildClass>::value,
"ParentClass is not base of ChildClass");
如果您没有C ++ 11支持,则可以使用boost::is_base_of
和BOOST_STATIC_ASSERT
。
答案 1 :(得分:2)
如果“Derived”继承自“Base”,则可以将指向“Derived”的指针分配给指向“Base”的指针。即:
void AssignToBase(Derived* derived) {
Base* base = derived;
}
...上述成功编译证明“Derived”继承自“Base”。您可以将此与SFINAE和静态断言(无论是在C ++ 11中还是使用Boost的静态断言机制)结合使用来验证派生类是否继承自父类。正如juanchopanza所说,C ++ 11提供了一个简单的std :: is_base_of&lt;&gt;类型traits类,可用于测试此继承关系。