如何重写QObject :: findChildren只返回派生类型

时间:2016-03-08 14:58:10

标签: c++ qt qobject

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

我想覆盖行为,以便只获取派生类型。

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

我尝试按如下方式覆盖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;
}

在我的例子中,我说四个项目是一个子项,两个是一个类型,两个是另一个,具有相同的基类。我为T传递了一个派生类型,并且正如预期的那样(现在)QObject :: findChildren给出了所有四个子节点。但我希望dynamic_cast只能成功两次,它会这样做四次。 如果我在模板函数之外传递返回的四个项目列表,我可以成功地将其剔除到我正在寻找的两个项目中。

1 个答案:

答案 0 :(得分:2)

修改 OP发现他在类层次结构中错误地使用了Q_OBJECT宏。我将离开他在下面接受的原始答案,但正确答案是必须在基础和派生类中使用Q_OBJECT宏。

原始回答: 如果QObject::findObject()确实使用reinterpret_cast<>,则即使无法表示类型,所有T的强制转换也会成功。根据API描述,这没有任何意义。但是,假设你在这一点上是正确的,那么你的实现是有缺陷的,因为你得到的是由于T而已经reinterpret_cast<>指针的兄弟姐妹列表。相反,您应该使用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;
}