让我说我有:
class Base {/*...*/}
class Derived1: public Base {/*...*/}
class Derived2: public Base {/*...*/}
..而且我有:
class SomeClass {
public:
template<typename DerivedType>
DerivedType GetDerived();
private:
vector<Base*> m_classes;
}
在GetDerived()
函数中,我通过m_classes向量迭代,我想做类似的事情:
if(m_classes[i] == DerivedType) {
return m_classes[i];
}
...并假设我们知道m_classes中的一个对象将包含一个'DerivedType'对象。
示例:
m_classes[2] = Base* BasePtr = new Derived1;
..在这种情况下,我想像这样使用GetDerived函数:
GetDerived<Derived1>();
..这应该返回m_classes [2]
我该怎么做?如何将基指针对象与派生类类型进行比较?更准确地说,GetDerived()
函数应该如何?
答案 0 :(得分:2)
您可以使用dynamic_cast<>
:
template<typename DerivedType>
std::vector<DerivedType*> GetDerived() { // note: return type changed
std::vector<DerivedType*> result;
for (DerivedType* at : this->m_classes) {
if (DerivedType* as = dynamic_cast<DerivedType*>(at)) {
result.push_back(as);
}
}
return result;
}
dynamic_cast<>
需要带有运行时类型信息的Base
类型(它将存在于具有虚函数的类型上)。
值得一提的是,有些人不喜欢dynamic_cast<>
,而某些约定/代码库禁止它。它是一种工具,可能会被滥用。
答案 1 :(得分:1)
通常做这样的事情并不是一个好主意。
如果对象不属于该类型,则可以使用返回nullptr
的{{3}},否则返回指向该类型的指针:
if (nullptr != dynamic_cast<DerivedType*>(m_classes[i]))
{ ... }
答案 2 :(得分:1)
正如其他人所说,你应该看看这是否真的是攻击你的问题的最好方法,但是{C}中提供了dynamic_cast
。您必须使用运行时类型标识或RTTI。
在编译器选项中打开它后,您可以在循环中执行此操作:
DerivedType* maybeDerived = dynamic_cast<DerivedType>(m_classes[i]);
if (maybeDerived)
return maybeDerived;
答案 3 :(得分:1)
当您需要以不同方式处理不同类的对象时,将它们存储在同一个容器中是一个坏主意。
然而, C ++有你正在寻找的东西,这一次。 dynamic_cast<B>(a)
会尝试将a
(无论是什么)转换为B
类型。如果运行时类不匹配,则返回nullptr
。
以下是编写GetDerived
的方法:
template <class Tsearched>
Tsearched *GetDerived() {
for(auto c : m_classes) {
if(Tsearched *ptr = dynamic_cast<Tsearched*>(c))
return ptr;
}
return nullptr;
}
或者,在标准算法的帮助下:
template <class Tsearched>
Tsearched *GetDerived() {
auto found = std::find_if(m_classes.begin(), m_classes.end(), [](Base *ptr) {
return dynamic_cast<Tsearched*>(ptr);
});
return found == m_classes.end() ? nullptr : static_cast<Tsearched*>(*found);
}
然而,让我再说一遍,这里有一个设计问题。 RTTI(dynamic_cast
使用的)既不优雅,也不快。
答案 4 :(得分:0)
您的示例语法无效。您无法在作业中声明声明。但是http://en.cppreference.com/w/cpp/types/is_base_of之类的东西可以帮助在编译时识别派生。至于在运行时识别派生类型,您可以使用dynamic_cast
,但理想的解决方案不应该这样做,这通常意味着您的对象或它们的使用方式存在潜在的设计缺陷。
正如@PaulMcKenzie指出的那样,你应该问自己&#34;为什么?&#34;在担心如何之前。