用于跟踪兄弟对象的QObject指针的静态QList

Static QList of QObject pointers to keep track of siblings?

本文关键字:指针 静态 QList QObject 用于 兄弟 对象 跟踪      更新时间:2023-10-16

我想通过将this(指向自身的指针)附加到"共享"静态QList类成员来跟踪thisClass(继承QObject)实例("兄弟")

private:
  static QList<thisClass*> _plist;

但是,static成员声明会导致LNK2001未解析的外部符号。如果没有static,程序就会构建(但每个对象只有自己的数据)。

可能导致错误的原因是什么,是否有修复方法,以及应该如何正确地"跟踪类实例"?

您已经声明了静态成员。现在您需要在cpp文件中定义它:

QList<thisClass*> thisClass::_plist;

您所做的只是一个声明,您还需要定义成员变量。这是在您的一个源文件中完成的。

如果你不需要列表的随机访问迭代,你也可以使用一个侵入式容器来允许兄弟节点的迭代:这会降低开销,因为列表节点存储在对象本身中。列表可以像std::list一样迭代,它跟踪对象的动态生存期——它与QPointer没有什么不同,只是它是一个列表。

// myclass.h - interface
#include <QObject>
#include <boost/intrusive/list.hpp>
class MyClass : public QObject, private boost::intrusive::list_base_hook<> {
  using list_t = boost::intrusive::list<MyClass>;
  static list_t m_siblings;
  friend list_t;
  static QThread const *listThread() {
    return m_siblings.empty() ? QThread::currentThread() : m_siblings.front().thread();
  }
protected:
  bool event(QEvent * ev) override {
    if (ev->type() == QEvent::ThreadChange)
      Q_ASSERT(m_siblings.size() <= 1);
    return QObject::event(ev);
  }
public:
  MyClass(QObject *parent = {}) : QObject{parent} {
    Q_ASSERT(listThread() == QThread::current_thread());
    m_siblings.push_back(*this);
    qDebug() << "there are" << m_siblings.size() << "objects in existence";
  }
  ~MyClass() override {
    m_list.erase(m_siblings.iterator_to(*this));
  }
};
// myclass.cpp - implementation
#include "myclass.h"
boost::intrusive::list<MyClass> MyClass::m_siblings;

强制要求所有兄弟姐妹都在同一个线程中;这对于列表的线程安全访问是必要的。如果对象生活在任意线程中,则列表访问需要由互斥对象保护:

// myclass.h - interface
#include <QObject>
#include <boost/intrusive/list.hpp>
class MyClass : public QObject, private boost::intrusive::list_base_hook<> {
  using list_t = boost::intrusive::list<MyClass>;
  static QReadWriteLock m_siblingsMutex;
  static list_t m_siblings;
  friend list_t;
public:
  MyClass(QObject *parent = {}) : QObject{parent} {
    QWriteLocker lock(&m_siblingsMutex);
    m_siblings.push_back(*this);
  }
  ~MyClass() override {
    QWriteLocker lock(&m_siblingsMutex);
    m_siblings.erase(m_siblings.iterator_to(*this));
  }
  void dumpSiblings() {
    QReadLocker lock(&m_siblingsMutex);
    for (auto const &obj : m_siblings)
       qDebug() << "MyClass at " << &obj;
};
// myclass.cpp - implementation
#include "myclass.h"
QReadWriteLock MyClass::m_siblingsMutex;
boost::intrusive::list<MyClass> MyClass::m_siblings;