Russian Qt Forum

Qt => Вопросы новичков => Тема начата: kambala от Июнь 06, 2012, 00:40



Название: [РЕШЕНО] правильная реализация паттерна Pimpl
Отправлено: kambala от Июнь 06, 2012, 00:40
Здравствуйте. Первый раз в жизни пришлось использовать паттерн Pimpl (pointer to implementation) для того, чтобы код имел нормальный вид (перед этим хедер был написан через #ifdef Q_WS_MACX #else #endif и просто ужасен, могу показать :) ). Покритикуйте пожалуйста - какие ошибки допущены, как сделать лучше.

Класс реализует простенький месседжбокс с чекбоксом и кнопками да/нет. В мак ос это просто обертка над NSAlert, а на других платформах - полноценный QDialog.

Вот тут прикреплён окончательный вариант реализации: http://www.prog.org.ru/index.php?topic=22129.msg154409#msg154409


Название: Re: правильная реализация паттерна Pimpl
Отправлено: Kurles от Июнь 06, 2012, 08:06
Здравствуйте. Первый раз в жизни пришлось использовать паттерн Pimpl (pointer to implementation) для того, чтобы код имел нормальный вид (перед этим хедер был написан через #ifdef Q_WS_MACX #else #endif и просто ужасен, могу показать :) ). Покритикуйте пожалуйста - какие ошибки допущены, как сделать лучше.

Класс реализует простенький месседжбокс с чекбоксом и кнопками да/нет. В мак ос это просто обертка над NSAlert, а на других платформах - полноценный QDialog.
Вроде все хорошо, но в самом Qt немного другая реализация. Вот здесь (http://habrahabr.ru/post/76248/) об этом подробно описано.


Название: Re: правильная реализация паттерна Pimpl
Отправлено: kambala от Июнь 06, 2012, 08:25
да, эту статью я читал, но для простенького случая там слишком много ненужного кода :)


Название: Re: правильная реализация паттерна Pimpl
Отправлено: Авварон от Июнь 06, 2012, 08:58
Неправильно всё. Нахрена там вообще виртуальность?


Название: Re: правильная реализация паттерна Pimpl
Отправлено: kambala от Июнь 06, 2012, 09:15
не придумал как по-другому сделать один из классов наследником QDialog при одном и том же интерфейсе


Название: Re: правильная реализация паттерна Pimpl
Отправлено: Авварон от Июнь 06, 2012, 09:38
Интерфейсом является сам класс. Наследования там не надо. Вы просто реализуете его ф-ии под конкретную платформу в отдельном файле. Если есть платформонезависимые ф-ии, реализуете их в общем .cpp. Линковщик сам подцепит нужную имплементацию.


Название: Re: правильная реализация паттерна Pimpl
Отправлено: Igors от Июнь 06, 2012, 12:19
Лучше смотрится так

Код
C++ (Qt)
class MessageCheckBoxImpl;
 
class MessageCheckBox
{
public:
   MessageCheckBox(const QString &text, const QString &checkboxText, QWidget *parent = 0);
   virtual ~MessageCheckBox();
 
   void setChecked(bool checked);
   bool isChecked();
 
   int exec();
 
private:
   MessageCheckBoxImpl * mImpl;
};
 
А потом 2 файла cpp для каждой из платформ. Да, придется в каждом написать напр MessageCheckBox::setChecked, но это лучше чем размазывать в хедере. Др словами более "идейно" не светить никаких деталей MessageCheckBoxImpl


Название: Re: правильная реализация паттерна Pimpl
Отправлено: kambala от Июнь 06, 2012, 14:46
спасибо, переделал (пркрепил к посту). но напрягает необходимость написания одной и той же реализации конструктора в обоих файлах реализаций:
Код
C++ (Qt)
MessageCheckBox::MessageCheckBox(const QString &text, const QString &checkboxText, QWidget *parent /*= 0*/) : _impl(new MessageCheckBoxImpl(text, checkboxText, parent)) {}


Название: Re: правильная реализация паттерна Pimpl
Отправлено: Igors от Июнь 06, 2012, 15:22
спасибо, переделал (пркрепил к посту). но напрягает необходимость написания одной и той же реализации конструктора в обоих файлах реализаций:
Код
C++ (Qt)
MessageCheckBox::MessageCheckBox(const QString &text, const QString &checkboxText, QWidget *parent /*= 0*/) : _impl(new MessageCheckBoxImpl(text, checkboxText, parent)) {}
Не вижу напряга, т.к. конструктор на платформу завязан. Вот если бы образовались методы которым не нужен impl (т.е. работают на уровне setChecked), то можно отнаследоваться (наследник уже платформо-независим)


Название: Re: правильная реализация паттерна Pimpl
Отправлено: kambala от Июнь 06, 2012, 17:59
в данном случае конструктор одинаков и там и там, потому получается дублирование кода :) может в таком случае лучше сделать MessageCheckBoxImpl структурой с нужными полями без всяких методов и конструкторов, а текущий конструктор MessageCheckBoxImpl перенести в конструктор MessageCheckBox?


Название: Re: правильная реализация паттерна Pimpl
Отправлено: Igors от Июнь 06, 2012, 18:17
в данном случае конструктор одинаков и там и там, потому получается дублирование кода :) может в таком случае лучше сделать MessageCheckBoxImpl структурой с нужными полями без всяких методов и конструкторов, а текущий конструктор MessageCheckBoxImpl перенести в конструктор MessageCheckBox?
Одинаков "формально", по написанию (и это не надолго). А на деле тело конструктора знает платформу, поэтому должно быть 2 тела, каждое в своем cpp. Думайте проще: отот impl должен быть в хедере "совсем бестелесным", с него извне ничего не взять даже если захотеть. Не надо бояться разумного дублирования, в конце-концов делегирование - тоже дубляж