如何在C++中比较类类型
How to compare class types in C++?
假设我得到了:
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()
函数应该是什么样子的?
当您需要以不同的方式处理不同类的对象时,将不同类的对象存储在同一个容器中是一个坏主意。
然而,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
使用的)既不优雅,也不快速。
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<>
,一些约定/代码库禁止它。它是一种工具,可能会被滥用。
通常做这样的事情不是一个好主意。
您可以使用dynamic_cast
,如果对象不是该类型,则返回nullptr
,否则返回指向该类型的指针:
if (nullptr != dynamic_cast<DerivedType*>(m_classes[i]))
{ ... }
正如其他人所说,您应该看看这是否真的是解决您的问题的最佳方法,但dynamic_cast
C++中可用。您必须使用运行时类型标识或 RTTI。
在编译器选项中打开它后,您可以在循环中执行此操作:
DerivedType* maybeDerived = dynamic_cast<DerivedType>(m_classes[i]);
if (maybeDerived)
return maybeDerived;
您的示例不是有效的语法。您不能在作业中间进行声明。但是,类似于 http://en.cppreference.com/w/cpp/types/is_base_of 的东西可以帮助在编译时识别派生。至于在运行时识别派生类型,您可以使用dynamic_cast
但理想的解决方案不需要这样做,这通常意味着您的对象或其使用方式存在潜在的设计缺陷。
正如@PaulMcKenzie所指出的,在担心如何之前,你可能应该问自己"为什么?"。
- 将模板化的类型与C++中的某些类/类型进行比较
- C++中"std::sort"比较器的不同类型
- 比较两个整数在C++中与未知 int 类型的相等性
- 如何使用变量模板比较 C++ 17 中的变量类型?
- 比较LLVM值的类型
- 用于比较基元类型的std::可选的有趣程序集
- 在C++中返回基元类型数组(Java比较)
- 为模板类中的特定类型编写比较器函数
- 为什么比较函数类型需要指定为模板参数?
- C++,"由于数据类型范围有限,比较总是正确的"
- 如何在C++中比较 lambda 函数的返回类型?
- C++ - 比较模板和类之间的数据类型
- 类型ID指针和引用比较差异?
- 在C++中,您能否像比较类型一样比较模板
- 使用具有自定义比较类型的关联容器时出现的问题
- 在Template中设置默认比较类型
- STL中使用的C++自定义比较类型(函数谓词与较少结构)
- C++类型比较:类型 ID 与双重调度dynamic_cast
- 比较类型指针
- double比较类型的变量总是返回false