Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
Kastaneda
Jesus loves me
Эксперт С++
5037 / 3056 / 349
Регистрация: 12.12.2009
Сообщений: 7,725
Записей в блоге: 2
Завершенные тесты: 1
1

С++ идиомы - обсуждение

01.08.2016, 11:59. Просмотров 923. Ответов 25
Метки нет (Все метки)

Тема создана для вопросов и обсуждений С++ идиом
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.08.2016, 11:59
Ответы с готовыми решениями:

С++ идиомы
Перевод статей 1 и 2. Будет постепенно обновляться. Желающие внести вклад могут писать в ЛС. ...

[с++][дизайн][сложность] обсуждение
всем привет. рассмотрим код: #pragma once #include <tools/text.h> #include <cassert>

Как и какие идиомы и паттерны можно (и лучше) применять?
Здравствуйте. Писал я проги для себя ну и так по мелочи, для абы кого, да и проги абы как, не...

Обсуждение своих программ
Ув.Программисты, решил открыть темку,где можно продемонстрировать свою прогу,обсуждать ее...

Классы для описания больницы (обсуждение)
Доброе время суток, в общем задали нам задание на написание куска программы из сферы "жизнь".... у...

25
Avazart
Эксперт С++
7823 / 5721 / 563
Регистрация: 10.12.2010
Сообщений: 26,163
Записей в блоге: 17
01.08.2016, 12:03 2
Не легче было в блоге разместить?
И редактировать легче и вести обсуждение.
0
Kastaneda
Jesus loves me
Эксперт С++
5037 / 3056 / 349
Регистрация: 12.12.2009
Сообщений: 7,725
Записей в блоге: 2
Завершенные тесты: 1
01.08.2016, 12:06  [ТС] 3
Avazart, в блог редко заглядывают, а тут на виду. Плюс в блоге придется самому все делать, а так коллективное творчество)
0
Avazart
Эксперт С++
7823 / 5721 / 563
Регистрация: 10.12.2010
Сообщений: 26,163
Записей в блоге: 17
01.08.2016, 12:14 4
Цитата Сообщение от Kastaneda Посмотреть сообщение
Avazart, в блог редко заглядывают, а тут на виду. Плюс в блоге придется самому все делать, а так коллективное творчество)
Я бы не сказал, кому надо заглядывают, при чем видят все, а вот в темы как раз смотрят реже.
Как по мне лучше когда все сосредоточено в одном месте одним тестом чем разбросано по постам.
Остальное (промежуточные варианты) можно в комментариях обсуждать, после чего помещать в текст блога.
0
01.08.2016, 12:14
Kastaneda
Jesus loves me
Эксперт С++
5037 / 3056 / 349
Регистрация: 12.12.2009
Сообщений: 7,725
Записей в блоге: 2
Завершенные тесты: 1
01.08.2016, 12:17  [ТС] 5
Avazart, спорный вопрос, я давно в блоги не заглядывал, а темы постоянно смотрю. Думаю я не один такой.
1
Ev_Hyper
Заблокирован
01.08.2016, 19:32 6
Kastaneda, смысл тему открывать/закрывать? Начнутся обсуждения, сообщения перенести и далее по списку. Телодвижений намного меньше выходит.
0
Kastaneda
Jesus loves me
Эксперт С++
5037 / 3056 / 349
Регистрация: 12.12.2009
Сообщений: 7,725
Записей в блоге: 2
Завершенные тесты: 1
01.08.2016, 19:38  [ТС] 7
Ev_Hyper, да, я вот тоже сегодня подумал об этом, человек хочет пост добавить, а меня на форуме нету, ему приходится ждать. Неудобно получается. Открываю тогда.
4
stu4ent
29 / 20 / 8
Регистрация: 23.09.2018
Сообщений: 186
04.10.2018, 01:13 8
Цитата Сообщение от meJevin Посмотреть сообщение
запрещает приведение из типа void *
не запрещает, а, наверно, не знает как это сделать, т.к. неизвестен размер типа

Добавлено через 51 секунду
Цитата Сообщение от meJevin Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
#define NULL 0
 
void func(int var) { std::cout << "Int" << std::endl; };
void func(double * ptr) { std::cout << "Double *" << std::endl; };
 
int main()
{
    func(static_cast <double *>(NULL)); // вызывается func(double *), как мы и хотели
 
    func(NULL); // запись интерпретируется, как func(0) - вызывается func(int).
                // но программист, скорее всего, хотел вызвать func(double *),
                // потому что NULL является константой нулевого УКАЗАТЕЛЯ,
                // которую мы определили ранее.
 
    return 0;
}
зачем отличать 0 указатель типа int от 0 указателя типа double?
0
Croessmah
++Ͻ
15325 / 8699 / 1660
Регистрация: 27.09.2012
Сообщений: 21,448
Записей в блоге: 2
Завершенные тесты: 2
04.10.2018, 09:20 9
Цитата Сообщение от stu4ent Посмотреть сообщение
не запрещает, а, наверно, не знает как это сделать, т.к. неизвестен размер типа
В C++ запрещено неявное преобразование из void *.
В C же не запрещено.
Цитата Сообщение от stu4ent Посмотреть сообщение
зачем отличать 0 указатель типа int от 0 указателя типа double?
NULL - имеет не указательный тип, что может подкинуть свинью.
Поэтому, например, был введен nullptr, дабы отличать.
0
hoggy
Эксперт С++
7116 / 3161 / 651
Регистрация: 15.11.2014
Сообщений: 7,264
Завершенные тесты: 1
04.10.2018, 20:31 10
Идиома "reference to implementation" (rImpl)

по смыслу - примерно тоже самое, что и pImpl,
однако, не использует дорогостоящую и потенциально не безопасную операцию выделения/освобождения памяти.
что делает rImpl более эффективной и надежной конструкцией.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// --- library.h
struct impl;      //<--- наша реализация. 
          // при желании можно запихнуть в потроха класса-хозяина
 
class agregat
{
public:
    agregat();
  ~agregat();  //<--- обязателен
private:
    enum { size = 4 };
    char storage[size];     //<--- в хедере отсвечивает лишь хранилище байт
        // я использовал обычный массив чар для иллюстрации
        // на самом деле можно использовать что то более надежное.
        // например конструкцию union, 
        // что бы гарантировать корректное выравнивание
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    // --- library.cpp
    #include <impl.h>    //<--- в спп файле прицепляем настоящую реализацию
       // теперь компилятору известен точный размер структуры
 
    namespace 
    {
        template<size_t N> impl& access(char (&storage)[N])
        {
            void* s = storage;
            auto* p =  reinterpret_cast<impl*>(s);
            return *p;
        }
 
    }//namespace 
 
    agregat::agregat()
    {
        // попросим компилятор проследить,
        // что хранилище нужного размера
        
        static_assert(
            agregat::size == sizeof(impl),
            "[ERROR] invalid type of 'impl'"
        );
        
        new (storage) impl();
    }
   agregat::~agregat()
   {
       // в деструкторе необходимо вручную позаботиться 
       // о разрушении объекта-реализации
       auto& obj = access(storage);
       obj.~impl();
   }
 
int main()
{
    agregat example;
}

нет нужды каждый раз в очередном классе вручную копипастить конструкцию rImpl.
его легко можно выделить в самостоятельный библиотечный класс,
а потом с удобством использовать много-много раз, как эффективную замену pImpl
0
Croessmah
++Ͻ
15325 / 8699 / 1660
Регистрация: 27.09.2012
Сообщений: 21,448
Записей в блоге: 2
Завершенные тесты: 2
04.10.2018, 22:50 11
hoggy, только не учитывается выравнивание.
0
hoggy
Эксперт С++
7116 / 3161 / 651
Регистрация: 15.11.2014
Сообщений: 7,264
Завершенные тесты: 1
05.10.2018, 11:18 12
Цитата Сообщение от Croessmah Посмотреть сообщение
только не учитывается выравнивание.
Цитата Сообщение от hoggy Посмотреть сообщение
// я использовал обычный массив чар для иллюстрации
* * * * // на самом деле можно использовать что то более надежное.
* * * * // например конструкцию union,
* * * * // что бы гарантировать корректное выравнивание
...
0
GbaLog-
Любитель чаепитий
3171 / 1476 / 466
Регистрация: 24.08.2014
Сообщений: 5,212
Записей в блоге: 1
Завершенные тесты: 2
12.10.2018, 05:44 13
Цитата Сообщение от hoggy Посмотреть сообщение
enum { size = 4 };
но ведь rimpl придётся перекомпилировать каждый раз, когда в impl добавляется/удалается поле.
pimpl как раз от этого и избавляет.
так что говорить, что по смыслу примерно то же самое мне не кажется до конца правдивым.
или я не прав?
0
hoggy
Эксперт С++
7116 / 3161 / 651
Регистрация: 15.11.2014
Сообщений: 7,264
Завершенные тесты: 1
12.10.2018, 11:44 14
Цитата Сообщение от GbaLog- Посмотреть сообщение
но ведь rimpl придётся перекомпилировать каждый раз, когда в impl добавляется/удалается поле.
pimpl как раз от этого и избавляет.
Цитата Сообщение от GbaLog- Посмотреть сообщение
или я не прав?
не прав)

в обоих случаях, что бы создать объект потребуется хедер с его классом.
в обоих случаях, что бы добавить поле - придется модифицировать хедер.
а значит, в обоих случаях придется перекомпилировать.


технически, можно заюзать модель вида:

C++
1
2
3
struct IBase { ... };
 
IBase* create(const int id); //<--- наследник живет в спп. наружу не торчит.
но это уже паттерн - "инъекция зависимостей", а не "прыщ" (pimple - прыщ с английского)
других способов порождать новых наследников без перекомпиляции не существует.

либо мы должны спрятать хедер наследника.
либо придется перекомпилировать.


хорошая новость заключается в том,
что предметная область pimpl/rimpl и не требует отказа от перекомпиляции.
поэтому, обычно фабрики не приплетают. а тупо жмакают ребилд.
0
Croessmah
++Ͻ
15325 / 8699 / 1660
Регистрация: 27.09.2012
Сообщений: 21,448
Записей в блоге: 2
Завершенные тесты: 2
12.10.2018, 12:40 15
Цитата Сообщение от hoggy Посмотреть сообщение
а значит, в обоих случаях придется перекомпилировать.
Только разные вещи придется перекомпилировать.
GbaLog- о том, что в канонической реализации,
если поменяется внутренняя реализация impl,
то придется перекомпилировать только library.cpp.
В приведенной же реализации, если поменяется impl,
нужно будет поменять размер в enum, а значит придется
перекомпилировать еще и всё, что зависит от agregat.
Также потеряется бинарная совместимость со старым agregat.

Добавлено через 5 минут

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
pimple - прыщ с английского
Только идиома называется pimpl а не pimple. :D

0
hoggy
Эксперт С++
7116 / 3161 / 651
Регистрация: 15.11.2014
Сообщений: 7,264
Завершенные тесты: 1
12.10.2018, 12:50 16
Цитата Сообщение от Croessmah Посмотреть сообщение
GbaLog- о том, что в канонической реализации,
если поменяется внутренняя реализация impl,
то придется перекомпилировать только library.cpp.
agregat.cpp зависит от library.h
добавление поля в класс ---> изменение файла library.h ---> перекомпиляция agregat.cpp

что бы этого избежать, необходимо спрятать library.h от agregat.cpp,
то бишь работать через интерфейс library,
реализация которого скрыта в library.lib

что и приводит нас к паттерну "инъекция зависимости" (англ. Dependency injection, DI)

Цитата Сообщение от Croessmah Посмотреть сообщение
Также потеряется бинарная совместимость со старым agregat.
код в принципе не должен закладываться на бинарную совместимость .
хотя бы уже потому, что у крестов отсутствует стандартное ABI.
вы не можете закладываться даже на бинарную совместимость одного и того же стандартного класса,
собранного одним и те же компилятором,
но с разными настройками,
без риска налететь на нарушения ODR

хорошая новость в том, что в 99% бинарная совместимость и не нужна.
0
Croessmah
++Ͻ
15325 / 8699 / 1660
Регистрация: 27.09.2012
Сообщений: 21,448
Записей в блоге: 2
Завершенные тесты: 2
12.10.2018, 13:02 17
Цитата Сообщение от hoggy Посмотреть сообщение
добавление поля в класс ---> изменение файла library.h ---> перекомпиляция agregat.cpp
Это про "rImpl", но еще за этим следует перекомпиляция всего остального, что зависит от library.h.
pImpl - добавление поля --> изменение только impl.h --> перекомпилируется только agregat.cpp.
0
hoggy
Эксперт С++
7116 / 3161 / 651
Регистрация: 15.11.2014
Сообщений: 7,264
Завершенные тесты: 1
12.10.2018, 14:03 18
Цитата Сообщение от Croessmah Посмотреть сообщение
Это про "rImpl", но еще за этим следует перекомпиляция всего остального, что зависит от library.h.
pImpl - добавление поля --> изменение только impl.h --> перекомпилируется только agregat.cpp.
не осилил "это про римпл"
потому что нет никакой разницы между пимплом в этом контексте.

потому что в обоих случаях последует перекомпиляция всего остального,
что зависит от impl.h, Кэп!!!
0
Croessmah
++Ͻ
15325 / 8699 / 1660
Регистрация: 27.09.2012
Сообщений: 21,448
Записей в блоге: 2
Завершенные тесты: 2
12.10.2018, 14:50 19
Цитата Сообщение от hoggy Посмотреть сообщение
потому что в обоих случаях последует перекомпиляция всего остального
Неа.

rImpl:
C++
1
2
3
4
5
6
7
//library.h
struct agregate
{
    //...
    enum { size = 4 };//При изменении строения impl, 
    char storage[size];//может потребоваться изменение размера буфера
};
C++
1
2
3
4
5
6
7
//impl.h
struct impl
{
    //sizeof(impl) == 4
    //изменение размера здесь приведет 
    //к необходимости изменения library.h
};
C++
1
2
3
4
5
6
//library.cpp
#include "library.h"
#include "impl.h"
 
//agregate implementation
//перекомпилируется в случае изменения libray.h или impl.h
C++
1
2
3
4
5
6
7
8
//всё_остальное.cpp
#include "library.h"
 
//реализация всего остального
//перекомпилируется в случае изменения
//заголовочного файла library.h
//например, если library.h - это интерфейс к DLL и меняется impl,
//то придется, помимо самой DLL перекомпилировать всё, что использует эту DLL.
А теперь к pImpl:
C++
1
2
3
4
5
6
7
8
9
//library.h
class impl;
struct agregate
{
    //...
    //Как бы не менялся impl, нам пофигу, 
    //здесь оно не поменяется никак.
    impl * pImple;
};
C++
1
2
3
4
5
6
7
//impl.h
struct impl
{
    //sizeof(impl) == 4
    //изменение размера или интерфейса 
    //здесь не приведет к изменению в library.h
};
C++
1
2
3
4
5
6
//library.cpp
#include "library.h"
#include "impl.h"
 
//agregate implementation
//перекомпилируется в случае изменения libray.h или impl.h
C++
1
2
3
4
5
6
7
8
9
10
//всё_остальное.cpp
#include "library.h"
 
//реализация всего остального
//перекомпилируется в случае изменения
//заголовочного файла library.h, который, как мы помним,
//не меняется от изменения файла impl.h
//например, если library.h - это интерфейс к DLL и меняется impl,
//то перекомпилировать придется только саму DLL,
//а то что, что использует эту DLL перекомпилировать не нужно.
0
hoggy
Эксперт С++
7116 / 3161 / 651
Регистрация: 15.11.2014
Сообщений: 7,264
Завершенные тесты: 1
12.10.2018, 14:55 20
Цитата Сообщение от Croessmah Посмотреть сообщение
Неа.
что значит неа?
и не нужно вырывать из контекста:
Цитата Сообщение от hoggy Посмотреть сообщение
потому что в обоих случаях последует перекомпиляция всего остального,
что зависит от impl.h, Кэп!!!
0
12.10.2018, 14:55
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.10.2018, 14:55

Лабораторная "Работа с файлами и структурами данных" - обсуждение
Здравствуйте, Есть такое задание: Составить программу со следующими свойствами: 1)вводится...

Тема-обсуждение для "Алгоритмов сортировок"
Сообщения выделены из закреплённой темы: http://www.cyberforum.ru/cpp-beginners/thread27084.html ...

Обсуждение написания сервера
Добрый день, недавно возник вопрос по написанию нагруженного сервера для одной клиентской...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru