5

Qt 文档建议将QSharedDataPointer 与其下级的可见实现一起使用是不典型的

所以根据文档中的小例子,我想出了以下来源(SSCCE)。

接口:Model.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'

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

这里并不严格要求复制构造函数,因为 EmployeeData 类与 Employee 类 (employee.h) 包含在同一个文件中。但是,在与包含 QSharedDataPointer 的公共类相同的文件中包含 QSharedData 的私有子类并不典型。通常,这个想法是通过将 QSharedData 的私有子类放在一个不会包含在公共文件中的单独文件中来对用户隐藏它。在这种情况下,我们通常会将 EmployeeData 类放在一个单独的文件中,该文件不会包含在 employee.h 中。相反,我们只需以这种方式在 employee.h 中预先声明私有子类 EmployeeData:

我想operator=在分配Model.

4

2 回答 2

5

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

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

  • 不管你写的是你使用了文档中原始示例的概念,你根本没有。您将复制构造函数的概念更改为复制分配。自然,您需要分别重新实现该运算符。

这是我为官方示例重写的工作示例,因为我认为为后代定制它比您的分歧示例更好地与上游内联以便更好地理解:

主文件

#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

员工_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;
}

主程序

TEMPLATE = app
TARGET = main
QT = core
HEADERS += employee.h employee_p.h
SOURCES += main.cpp employee.cpp
于 2014-12-27T13:54:16.820 回答
0

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

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

新界面:Model.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.

于 2014-12-27T13:47:18.183 回答