简体   繁体   English

静态QList的QObject指针来跟踪兄弟姐妹吗?

[英]Static QList of QObject pointers to keep track of siblings?

I would like to keep track of thisClass (inherits QObject) instances ("siblings") by appending this (the pointer to self) to a "shared" static QList class member: 我想通过this (指向self的指针)附加到“共享的”静态QList类成员thisClass跟踪thisClass (继承QObject)实例(“兄弟”):

private:
  static QList<thisClass*> _plist;

However, the static member declaration causes an LNK2001 unresolved external symbol. 但是, static成员声明会导致LNK2001无法解析的外部符号。 Without static , the program builds (but each object only has its own data). 如果没有static ,则程序会生成(但是每个对象只有自己的数据)。

What might cause the error, is there a fix, and how should "keeping track of class instances" be done properly? 可能导致该错误的原因是什么,是否有修复程序,以及如何正确完成“跟踪类实例”?

You have declared static member. 您已声明静态成员。 Now you need to define it in cpp file: 现在您需要在cpp文件中定义它:

QList<thisClass*> thisClass::_plist;

What you have done is only a declaration , you also need to define the member variable. 您所做的只是一个声明 ,还需要定义成员变量。 This is done in one of your source files. 这是在您的一个源文件中完成的。

If you don't need random access iteration of the list, you could also use an intrusive container to allow iteration of the siblings: it'd have lower overhead, as the list nodes are stored in the objects themselves. 如果不需要列表的随机访问迭代,则还可以使用侵入式容器来允许兄弟姐妹进行迭代:由于列表节点存储在对象本身中,因此开销较低。 The list can be iterated just like std::list , and it tracks the dynamic lifetime of the objects - it's not unlike like a QPointer , except that it's a list. 该列表可以像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;

It is enforced that all siblings are in the same thread; 强制所有兄弟姐妹都在同一线程中。 this is necessary for thread-safe access of the list. 这对于列表的线程安全访问是必需的。 If the objects were to live in arbitrary threads, the list access needs to be protected by a mutex: 如果对象驻留在任意线程中,则列表访问需要通过互斥来保护:

// 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM