带有前向声明类的QSharedDataPointer

时间:2014-12-27 12:36:45

标签: c++ qt qtcore qshareddata

Qt documentation表明使用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)。但是,包括QSharedData的私有子类   在与包含QSharedDataPointer的公共类相同的文件中   不典型。通常,这个想法是隐藏私有子类   来自用户的QSharedData将其放在一个单独的文件中   不包含在公共文件中。在这种情况下,我们通常会   将类EmployeeData放在一个单独的文件中,该文件不包括在内   在employee.h中。相反,我们只是预先声明私有子类   employee.h中的EmployeeData这样:

我认为在分配operator=时使用的Model编译失败。

2 个答案:

答案 0 :(得分:5)

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

  • 您需要将私有类放在单独的文件中,以便与原始想法不同。

  • 无论您是在写这篇文章,都使用了文档中原始示例的概念,但您根本没有。您更改了复制构造函数概念以复制assighment。当然,您需要分别重新实现该运算符。

以下是我对官方示例进行重写的工作示例,因为我认为最好为后代定制,而不是为了更好的理解,为了更好的理解而更好地与上游进行内联:

的main.cpp

#include "employee.h"

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

employee.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

employee.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

答案 1 :(得分: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