在基向量中查找派生对象

问题描述 投票:0回答:2

我在某个项目中创建了以下代码:

std::vector<Base*> objs_;

template <class TDerived>
T* Get() {
  auto objIt = std::find_if(objs_.cbegin(), objs_.cend(), [](Base* it) {
    return typeid(TDerived).name() == typeid(*it).name();
  });
  return objIt == objs_.cend() ? nullptr : *objIt;
}

我想弄清楚,使用

typeid
是一个不错的选择吗? 因为C++有
dynamic_cast
例如:

template <class TDerived>
T* Get() {
  auto objIt = std::find_if(objs_.cbegin(), objs_.cend(), [](Base* it) {
    return dynamic_cast<T*>(it) != nullptr;
  });
  return objIt == objs_.cend() ? nullptr : *objIt;
}

(我知道上面的解决方案之间存在语义差异,因为

dynamic_cast
也会抱怨
TDerived
继承者,但是没关系,所有使用的
TDerived
都是
final

typeid
是一个好的选择,还是
dynamic_cast
更好或者有更好的解决方案?

c++ oop casting polymorphism rtti
2个回答
1
投票

你不能比较名称,因为它们不必为相同的类型具有相同的指针值。例如,

typeid(TDerived).name() == typeid(TDerived).name()
可以是假的。

你应该直接比较 typeids 而不是

std::type_info::operator==
:

    return typeid(TDerived) == typeid(*it);

至于这是否比

dynamic_cast
更好,那要看情况了。对于您提到的最后一堂课,语义上没有区别。我认为比较
typeid
s会让你的意图更清晰。


0
投票

不,

typeid
根本不是一个好主意,因为子类型之一涉及的类型将需要丰富检查
typeid
的部分。这又是开/闭原则

顺便说一句,

typeid
有很多微妙的问题,例如返回的类型名称没有标准化,而且,正如在 cppreference 上指出的那样:

不能保证同一个 std::type_info 实例将被同一类型上 typeid 表达式的所有评估所引用,尽管它们比较相等,这些 type_info 对象的 std::type_info::hash_code 将是相同的,就像他们的 std::type_index 一样。

dynamic_cast
的使用稍微好一些,因为如果不添加新类型,它可能允许遵守开放/封闭原则。但如果这样做,您将再次丰富代码。此外,
dynamic_cast
要求使用类/函数了解很多关于使用的类。这可能会削弱 encapsulation 并创建隐藏的耦合(即您不能再根据需要更改使用的类,因为您轻而易举地打破了一些假设)

最好的办法是用多态的方式重写代码。 C++ 核心指南在这方面提醒说,virtual functions should be preferred to casting。更一般地说,该方法应该使用告诉不问原则,让多态代码做它必须做的事情。或者选择访客模式

© www.soinside.com 2019 - 2024. All rights reserved.