带有前向声明类的 QSharedDataPointer

QSharedDataPointer with forward-declared class

本文关键字:QSharedDataPointer 声明      更新时间:2023-10-16

Qt文档表明,使用QSharedDataPointer 及其劣质的可见实现并不典型

因此,根据文档中截取的小示例,我想出了以下来源(SSCCE)。

界面:模型.h

接口很简单,只是私有类和句柄类的前向声明,声明了 copy-ctor 和 d-tor:

#include <QtCore/QSharedDataPointer>
class ModelPrivate;
class Model {
    public:
        Model();
        Model(const Model &other);
        ~Model();
        QSharedDataPointer<ModelPrivate> d;
};

专用标头:Model_p.h

只是声明和定义下级类。

#include <QSharedData>
class ModelPrivate:
    public QSharedData {
    public:
};

实施:Model.cc

包括 c-tors/d-tor 的实现,取自文档。

#include "Model.h"
#include "Model_p.h"
class ModelPrivate:
    public QSharedData {
};
Model::Model():
    d(new ModelPrivate()) {
}
Model::Model(const Model &other):
    d(other.d) {
}
Model::~Model() {
}

用例:main.cc

一切都失败了。

#include <QString>
#include "Model.h"
int main(int argc, char *argv[]) {
    QString s1, s2;
    s2 = s1;
    Model m1, m2;
    m2 = m1;
}

只有两个实例和一个赋值,就像任何其他共享类一样。但是,由于以下原因,它失败得很严重

invalid use of incomplete type 'class ModelPrivate'

我无法弄清楚如何根据文档以预期的方式使其工作,即没有在标头中完全声明私有类。我知道这样做时它有效,但我想了解文档。分配共享类的示例也包含在文档中。从上面链接的文档:

这里并不严格要求复制构造函数,因为类 员工数据包含在与类员工相同的文件中 但是,包括 QSharedData 的私有子类。 与包含 QSharedDataPointer 的公共类位于同一文件中 不典型。通常,这个想法是隐藏私有子类 QShared数据从用户,将其放在一个单独的文件中,这将 不包含在公共文件中。在这种情况下,我们通常会 将类 EmployeeData 放在一个单独的文件中,该文件将不包含在内 在员工中。相反,我们只是预先声明私有子类 员工数据在 employee.h 中是这样:

我想编译在分配Model时使用的operator=失败.

您的概念有几个主要问题:

  • 确实需要将私有类放在单独的文件中才能做到这一点,这与您最初的想法不同。

  • 无论您是否在编写是否使用了文档中原始示例的概念,您都没有。您将复制构造函数概念更改为复制辅助。当然,您需要分别重新实现该运算符。

这是我为官方示例重写的工作示例,因为我认为为后代自定义它比您的发散示例更好,以便与上游更一致以便更好地理解:

主.cpp

#include "employee.h"
int main()
{
    Employee e1(1001, "Albrecht Durer");
    Employee e2 = e1;
    Emplyoee e3;
    e3 = e2;
    e1.setName("Hans Holbein");
}

员工.h

#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include <QSharedDataPointer>
#include <QString>
class EmployeeData;
class Employee
{
  public:
    Employee();
    Employee(int id, QString name);
    Employee(const Employee &other);
    Employee& operator =(const Employee &other);
    ~Employee();
    void setId(int id);
    void setName(QString name);
    int id() const;
    QString name() const;
  private:
    QSharedDataPointer<EmployeeData> d;
};
#endif

employee_p.h

#ifndef EMPLOYEE_P_H
#define EMPLOYEE_P_H
#include <QSharedData>
#include <QString>
class EmployeeData : public QSharedData
{
  public:
    EmployeeData() : id(-1) { }
    EmployeeData(const EmployeeData &other)
        : QSharedData(other), id(other.id), name(other.name) { }
    ~EmployeeData() { }
    int id;
    QString name;
};
#endif

员工.cpp

#include "employee.h"
#include "employee_p.h"
Employee::Employee()
{
    d = new EmployeeData;
}
Employee::Employee(int id, QString name)
{
    d = new EmployeeData;
    setId(id);
    setName(name);
}
Employee::Employee(const Employee &other)
: d (other.d)
{
}
Employee& Employee::operator =(const Employee &other)
{
    d = other.d;
    return *this;
}
Employee::~Employee()
{
}
void Employee::setId(int id)
{
    d->id = id;
}
void Employee::setName(QString name)
{
    d->name = name;
}
int Employee::id() const
{
    return d->id;
}
QString Employee::name() const
{
    return d->name;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
HEADERS += employee.h employee_p.h
SOURCES += main.cpp employee.cpp

问题实际上在于通过 QSharedDataPointer 类中的模板声明和定义的 d 成员的赋值运算符。

该解决方案就像将共享类的赋值运算符移动到模块中一样简单:

新界面:模型.h

#include <QtCore/QSharedDataPointer>
class ModelPrivate;
class Model {
    public:
        Model();
        Model(const Model &other);
        Model &operator =(const Model &other); /* <-- */
        ~Model();
        QSharedDataPointer<ModelPrivate> d;
};

专用标头:Model_p.h

#include <QSharedData>
class ModelPrivate:
    public QSharedData {
    public:
};

实现: Model.cc:

#include "Model.h"
#include "Model_p.h"
Model::Model():
    d(new ModelPrivate()) {
}
Model::Model(const Model &other):
    d(other.d) {
}
Model::~Model() {
}
Model &Model::operator =(const Model &other) {
    d = other.d;
    return *this;
}

用例:main.cc

#include <QString>
#include "Model.h"
int main() {
    QString s1, s2;
    s2 = s1;
    Model m1, m2;
    m2 = m1;
}

项目文件:example.pro

TEMPLATE = app
TARGET = example
QT = core
HEADERS += Model.h Model_p.h
SOURCES += Model.cc main.cc

事实上,这就是Qt宇宙本身中其他类的实现方式。例如,考虑QTextCursor .

相关文章:
  • 没有找到相关文章