Скрыть дебри с линковкой
От: Kingofastellarwar Украина  
Дата: 02.11.15 14:59
Оценка:
вопрос по дизайну
в с++ лучший способ скрыть дебри реализации это ничего не экспортировать и не линковать, а предоставить тока абстрактные интерфейсы наружу
а можно както тоже самое сделать но с линковкой? причем не через жо а красиво?

на одном проекте пробую избавиться в модуле от интерфейсов(напрягает по 3 файла на один класс и на каждый пук менять метод в 3х местах)
да и не нравится что я не могу наследовать ничего при таком подходе, а какойто полезной изоляции такой подход не даёт, кроме того что можно независимо компилировать
но при таком подхоже тот к кому линкует хочет видеть все внешние инклуды линкуемого, что не прикольно, да и линковкой могут быть подобные проблемы
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re: Скрыть дебри с линковкой
От: Evgeny.Panasyuk Россия  
Дата: 02.11.15 15:32
Оценка: +1
Здравствуйте, Kingofastellarwar, Вы писали:

K>на одном проекте пробую избавиться в модуле от интерфейсов(напрягает по 3 файла на один класс и на каждый пук менять метод в 3х местах)


Как вариант — pimpl:
// PUBLIC:

class Widget
{
    struct implementation;
    unique_ptr<implementation> impl;
public:
    Widget();
    ~Widget();

    int method();
};

// PRIVATE:

struct Widget::implementation
{
    int data;
};

Widget::Widget()
    : impl(make_unique<implementation>())
{}

Widget::~Widget() = default;

int Widget::method()
{
    return impl->data;
}
Re[2]: Скрыть дебри с линковкой
От: Tasheehoo  
Дата: 03.11.15 10:45
Оценка:
Позвольте два оффтопных вопроса.

1)Какой смысл использовать unique_ptr для pimpl? Только чтоб не звать в деструкторе delete?
EP>class Widget
EP>{
EP> struct implementation;
EP> unique_ptr<implementation> impl;

2)Зачем тут писать default?
EP>Widget::~Widget() = default;


Спасибо.
Re[3]: Скрыть дебри с линковкой
От: watchmaker  
Дата: 03.11.15 11:18
Оценка: 6 (1) +3
Здравствуйте, Tasheehoo, Вы писали:


T>1)Какой смысл использовать unique_ptr для pimpl? Только чтоб не звать в деструкторе delete?

Ты так говоришь, как будто это сама по себе не достаточная причина.

T>2)Зачем тут писать default?

EP>>Widget::~Widget() = default;
Чтобы unique_ptr<T> смог разрушить объект, T должен быть complete типом. Если не написать явно деструктор, то компилятор сгенерирует свой автоматически, но в нём тип T будет incomplete (очевидно, что из заголовочного файла не видно внутренностей implementation, и implementation таким образом не будет полностью определённым).
Существенно тут то, что декструктор реализован в точке в которой известны внутренности implementation.

Или вопрос в том, почему написано Widget::~Widget() = default; вместо Widget::~Widget() {} ? Ну это просто такой способ чуть яснее показать семантику, что тут важно именно место реализации, а сам деструктор подойдёт и созданных компилятором (по аналогии с default реализациями операций перемещения или копирования).
Отредактировано 03.11.2015 11:30 watchmaker . Предыдущая версия . Еще …
Отредактировано 03.11.2015 11:29 watchmaker . Предыдущая версия .
Re[3]: Скрыть дебри с линковкой
От: Evgeny.Panasyuk Россия  
Дата: 03.11.15 11:26
Оценка:
Здравствуйте, Tasheehoo, Вы писали:

T>Позвольте два оффтопных вопроса.

T>1)Какой смысл использовать unique_ptr для pimpl? Только чтоб не звать в деструкторе delete?

Попробуй напиши вариант с delete — сравним.
Re[4]: Скрыть дебри с линковкой
От: Tasheehoo  
Дата: 03.11.15 11:42
Оценка:
Здравствуйте, watchmaker, Вы писали:
W>Чтобы unique_ptr<T> смог разрушить объект, T должен быть complete типом. Если не написать явно деструктор, то компилятор сгенерирует свой автоматически, но в нём тип T будет incomplete (очевидно, что из заголовочного файла не видно внутренностей implementation, и implementation таким образом не будет полностью определённым).
W>Существенно тут то, что декструктор реализован в точке в которой известны внутренности implementation.
Как-то не задумывался об этом... Но логично.

W>Или вопрос в том, почему написано Widget::~Widget() = default; вместо Widget::~Widget() {} ? Ну это просто такой способ чуть яснее показать семантику, что тут важно именно место реализации, а сам деструктор подойдёт и созданных компилятором (по аналогии с default реализациями операций перемещения или копирования).

Да, вопрос был именно в этом.

Спасибо.
Re[4]: Скрыть дебри с линковкой
От: Tasheehoo  
Дата: 03.11.15 11:44
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Попробуй напиши вариант с delete — сравним.

А что тут сравнивать? Вроде все тривиально...
// PUBLIC:

class Widget
{
    struct implementation;
    implementation *impl;
public:
    Widget();
    ~Widget();

    int method();
};

// PRIVATE:

struct Widget::implementation
{
    int data;
};

Widget::Widget()
    : impl(new implementation)
{}

Widget::~Widget()
{ delete impl; }

int Widget::method()
{
    return impl->data;
}
Re[5]: Скрыть дебри с линковкой
От: Evgeny.Panasyuk Россия  
Дата: 03.11.15 11:53
Оценка:
Здравствуйте, Tasheehoo, Вы писали:

EP>>Попробуй напиши вариант с delete — сравним.

T>А что тут сравнивать? Вроде все тривиально...

Rule of three не выполнено — получаем вполне закономерные фейерверки и утечки:
http://coliru.stacked-crooked.com/a/5ccf8ea01d07ac5b
int main()
{
    Widget x, y;
    x = y;
}

*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x0000000002414c40 ***
Re[6]: Скрыть дебри с линковкой
От: Tasheehoo  
Дата: 03.11.15 13:23
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Rule of three не выполнено — получаем вполне закономерные фейерверки и утечки:

Это и понятно. Я же могу перегрузить нужный конструктор и operator=.

Я правильно понимаю, что для случая когда объект не копируемый, использование обычного указателя на реализацию вполне достаточно?
Re[7]: Скрыть дебри с линковкой
От: Evgeny.Panasyuk Россия  
Дата: 03.11.15 21:58
Оценка:
Здравствуйте, Tasheehoo, Вы писали:

EP>>Rule of three не выполнено — получаем вполне закономерные фейерверки и утечки:

T>Это и понятно. Я же могу перегрузить нужный конструктор и operator=.

Ну так сделай полный эквивалент, без double free и leaks, и сравни side-by-side оба варианта.

T>Я правильно понимаю, что для случая когда объект не копируемый, использование обычного указателя на реализацию вполне достаточно?


Внутри unique_ptr никакой магии — конечно всё можно вручную каждый раз расписывать. Но зачем?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.