QSharedDataPointer с объявленным заранее классом

Документация Qt предполагает, что использование QSharedDataPointer с видимой реализацией его подчиненного не типично.

Итак, в соответствии с небольшим примером, приведенным в документации, я нашел следующий источник (SSCCE).

Интерфейс: Model.h

Интерфейс прямой, просто предварительное объявление частного класса и класса handle, с объявленными 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. Вместо этого мы просто объявили бы частный подкласс
EmployeeData в employee.h таким образом:

Я полагаю, сборка не удалась на operator= который используется при назначении Model,

5

Решение

У вас есть несколько основных проблем с вашей концепцией:

  • Вам нужно иметь закрытый класс в отдельных файлах, чтобы сделать это красиво, в отличие от вашей первоначальной идеи.

  • Независимо от того, что вы пишете, что вы использовали концепцию оригинального примера из документации, вы просто этого не сделали. Вы изменили концепцию конструктора копирования на назначение копирования. Естественно, вам нужно переопределить этот оператор, соответственно.

Вот мой рабочий пример переписывания для официального примера, так как я думаю, что лучше настроить его для потомков, чем для вашего разнородного примера, чтобы он был более последовательным с исходным кодом для лучшего понимания:

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
5

Другие решения

Проблема в том, что оператор присваивания 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,

0

По вопросам рекламы [email protected]