Закрытый (скрытый) QSharedData

У меня есть класс, в котором есть некоторые элементы данных, которые я хочу скрыть от вызывающей стороны (потому что включение заголовков для их типов значительно увеличивает время компиляции, и для каждого проекта, использующего этот класс, потребуется добавить дополнительный путь к своим путям включения.).

Этот класс использует QSharedDataPointer хранить эти данные. Таким образом, его можно скопировать с помощью конструктора копирования по умолчанию.

Базовая структура этого класса:

class MyClass {
private:
  QSharedDataPointer<MySharedClassData> m_data;
};

Есть ли какой-нибудь причудливый трюк, чтобы сделать это без определения MySharedClassData (который наследует от QSharedData) в том же заголовочном файле? Или есть какой-то другой способ скрыть поля данных?

Я уже попробовал предварительную декларацию MySharedClassData но это не сработало (несмотря на то, что m_data является private).

Единственное решение, которое я могу сейчас сделать, это объявить m_data как QSharedDataPointer<QSharedData> но тогда мне нужно приводить элемент данных каждый раз, когда я хочу получить к нему доступ. Есть ли лучшее решение?

3 ответа

Решение

Форвардное объявление должно работать, пока ваш конструктор и деструктор не определены в заголовке. Следующий класс компилируется на моем компьютере:

#ifndef MAIN_WINDOW_HXX
#define MAIN_WINDOW_HXX

#include <QMainWindow>
#include <ui_MainWindow.h>

#include <QSharedDataPointer>

class MySharedClassData;

class MainWindow : public QMainWindow, private Ui_MainWindow {
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0);
    virtual ~MainWindow();

    QSharedDataPointer<MySharedClassData> m_data;

};

#endif

Если вы попытаетесь встроить свой конструктор / деструктор, то вы можете получить: C2027: use of undefined type 'type' под VS.

В общем, если вы хотите использовать идиому pimpl с интеллектуальным указателем на ранее объявленный impl (а не управлять объектом impl вручную), вам нужен интеллектуальный указатель с удаленным удалением, например boost::shared_ptr (вы должны быть в состоянии использовать std::unique_ptr с пользовательским удалителем, но я не пробовал).

Требование заключается в том, что вы можете создать экземпляр шаблона смарт-указателя, не видя деструктор класса impl: это исключает std::auto_ptr например.

Не знаю QSharedDataPointer отвечает требованию или нет, но тибур, кажется, говорит, что это так.

Да. Там нет действительно причудливый трюк не требуется. Тем не менее, все методы, которые нужны MySharedClassData должны быть определены после определения MySharedClassData, Если вы переместите определение класса в файл.cpp, методы также должны быть перемещены туда.

Другие вопросы по тегам