如何仅将派生类型覆盖 QObject::findChildren 到 return

How to override QObject::findChildren to return only the derived type

通过回答我自己的另一个问题 (here),我发现 QObject::findChildren<T> 将 return 任何通过 reinterpret_cast<T> 的 child .

我想重写该行为,以便我只获得派生类型。

这是因为我有一个复合模式,其中所有项目都是相同的基本类型,但我想使用 findChildren 来查找特定的 sub-classes。

我尝试如下覆盖 findChildren:

template <class T> 
QList<T> Section::findChildren(QString name)
{
  QList<T> siblings = QObject::findChildren<T>(name);
  QList<T> children;
  for(int i=0; i < siblings.size(); i++)
  {    
    T test = siblings.at(i);
    T child = dynamic_cast<T>(test);
    if(child)
      children << child;
  }
  return children;
}

在我的示例中,我说了四个项目 children,两个是一种类型,两个是另一种类型,具有相同的基数 class。我为 T 传递了一种派生类型,正如预期的那样(现在)QObject::findChildren 给出了所有四个 children。但我预计 dynamic_cast 只会成功两次,它会成功四次。 如果我在模板函数之外传递包含四个项目的 returned 列表,我可以成功地将其剔除为我正在寻找的两个项目。

编辑: OP 发现他在 class 层次结构中错误地使用了 Q_OBJECT 宏。我将在下面留下他接受的原始答案,但正确答案是必须在基础和派生的 classes.

中使用 Q_OBJECT

原始答案: 如果 QObject::findObject() 真的使用了 reinterpret_cast<>,那么所有对 T 的转换都会成功,即使无法表示类型。根据 API 的描述,这没有任何意义。但是,假设您在这一点上是正确的,那么您的实现是有缺陷的,因为由于 reinterpret_cast<>,您得到的兄弟姐妹列表已经是 T 指针。相反,您应该使用 QObject 然后使用 dynamic_cast<> 来清除您想要的实例,如下所示:

template <class T> 
QList<T> Section::findChildren(QString name)
{
  QList<QObject*> siblings = QObject::findChildren<QObject*>(name);
  QList<T> children;
  for(int i=0; i < siblings.size(); i++)
  {    
    QObject* test = siblings.at(i);
    T child = dynamic_cast<T>(test);
    if(child)
      children << child;
  }
  return children;
}