Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
Заблокирован

Сложность абстракции, полиморфизм, дублирование и другие

25.11.2011, 23:57. Показов 5461. Ответов 58
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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
//структура "матрица"
//Представляет собой обёртку над двухмерным массивом
template<typename TypeT, int _SizeX, int _sizeY>
struct Array2D
{
    Array2D()
    {
        for(int y = 0; y < _sizeY; ++y)
        {
            for(int x = 0; x < _SizeX; ++x)
            {
               Arr[x][y] =  rand()%100 + 1;
            }
        }
    }
    TypeT Arr[_SizeX][_sizeY];
};
 
//создаём 100 штук таких матриц
//каждая матрица будит проинициализирована
//случайными числами
Array2D<int,100,100> SuperArray[100];
 
 
int main()
{
   return 0;
};
Добавлено через 5 минут
Цитата Сообщение от silent_1991 Посмотреть сообщение
proger2030, вы читаете, что вам пишут? Используйте трёхмерные массивы (т.е. массивы двухмерных массивов, с логической точки зрения), в самом верхнем цикле перебирая двухмерные массивы, а во вложенных заполняя каждый из них.
Настоятельно не рекомендую использовать трехмерные массивы.
Более того, крайне не рекомендую использовать двухмерные массивы.

Одномерный массив намного проще для понимания, и гибче в управлении.
Его легче трансформировать во всевозможные состояния.

Если так сильно понадобились многомерные массивы - всегда можно инкапсулировать сложность абстракции внутри нового класса.

Массивы массивов намного гибче и проще в плане всевозможных трансформаций/сортировок и тп.
Не придётся голову ломать над глючной адресной арифметикой многомерных массивов.

Всегда нужно стремится понижать сложность архитектуры. Для этого и существуют классы.

 Комментарий модератора 
Корни темы здесь - Как создать 100 массивов разными значениями ?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.11.2011, 23:57
Ответы с готовыми решениями:

Одновременное дублирование строк на другие листы по условию
Всех с Новым годом! Есть таблица данных, ежедневно пополняемая! Задача в том, чтобы при пополнении основной таблицы, строки...

Как сделать дублирование изображения формы 2 на первую с компонентом Panel или другие варианты
Как сделать дублирование изображения с формы 2 и обновление его на форме 1 с помощью Panel или другими компонентами или методами?

Как вычислять сложность алгоритма, или найти асимптотическую сложность любой программки?
Например Вычислить x^n по алгоритму быстрого возведения в степень Добавлено через 43 секунды var x, n, r: word; ...

58
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
26.11.2011, 00:30
Лучший ответ Сообщение было отмечено как решение

Решение

Bers, если Вы так настоятельно рекомендуете, то за Вас уже давно постарались: есть std::vector, есть std::array. Смысла писать собственный костыль по имени Array2D я не вижу. То есть я настоятельно рекомендую пользоваться классами стандартной библиотеки! Чтобы избежать возникновения вероятных ошибок. Я повторяю, я настоятельно рекомендую!
3
Заблокирован
26.11.2011, 00:47  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Bers, если Вы так настоятельно рекомендуете, то за Вас уже давно постарались: есть std::vector, есть std::array. Смысле писать собственный костыль по имени Array2D я не вижу. То есть я настоятельно рекомендую пользоваться классами стандартной библиотеки! Чтобы избежать возникновения вероятных ошибок. Я повторяю, я настоятельно рекомендую!
Смысл написания "костылей" по имени Array2D - понижение сложности архитектуры.
Очень важно знать как это можно сделать. И знать, когда это нужно применять.

А вот что именно вы там используете в основе новой абстракции - вектор векторов, или собственный велосипед - это уже личное дело каждого, и к идее моей рекомендации отношения не имеет. Я не зря написал "не суть".

Смысл моей идеи прост: "разделяй и властвуй".

А по поводу вектора - оставьте свои рекомендации для новичков. Мне об этом говорить не нужно.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
26.11.2011, 00:51
Цитата Сообщение от Bers Посмотреть сообщение
Смысл написания "костылей" по имени Array2D - понижение сложности архитектуры.
Очень важно знать как это можно сделать. И знать, когда это нужно применять.
Понижая сложность архитектуры, Вы порождаете дублирующий код. Избегая одного зла - производите другое. И это однозначно не выход. Отсюда я позволяю себе сделать вывод о том, что Вы не знаете как делать правильно и когда это необходимо.

Не по теме:

Цитата Сообщение от Bers Посмотреть сообщение
А по поводу вектора - оставьте свои рекомендации для новичков. Мне об этом говорить не нужно.
Вообще я иронизировал на тему Вашей же привычки отпускать рекомендации ;)

0
Заблокирован
26.11.2011, 00:59  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Понижая сложность архитектуры, Вы порождаете дублирующий код.
1. Я не понял про "порождение дублирующего кода". Поясните эту мысль.

2. Между сложностью решения, и дублированием лично я выбираю второе. Пускай будит уйма дублированного кода, вплоть до хардкорной копипасты, если при этом удастся погасить сложность общего решения. Чем проще архитектура, тем она безопаснее. В таком коде всегда меньше всего ошибок. Его проще сопровождать. Он быстрее конструируется.
Самый простой код - продукт продуманной архитектуры. И бла бла бла.

3. Элегантное решение с применением того же самого полиморфизма порождает очень много дублированного кода. Но никого это особо не парит. Что характеризует.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
26.11.2011, 01:06
Цитата Сообщение от Bers Посмотреть сообщение
Я не понял про "порождение дублирующего кода". Поясните эту мысль.
Я уже сказал выше, но да ладно, пусть будет. Вы порождаете сущность, которая дублирует функционал уже существующих сущностей. А именно std::array как минимум. При чем делает это хуже. Я бы еще понял, если бы Вы создали обертку над std::array, но нет же, не вижу такого здесь.
Цитата Сообщение от Bers Посмотреть сообщение
Между сложностью решения, и дублированием лично я выбираю второе. Пускай будит уйма дублированного кода, вплоть до хардкорной копипасты, если при этом удастся погасить сложность общего решения. Чем проще архитектура, тем она безопаснее. В таком коде всегда меньше всего ошибок. Его проще сопровождать. Он быстрее конструируется.
И о чем с Вами прикажете разговаривать после такого, господин Архитектор?
Цитата Сообщение от Bers Посмотреть сообщение
Элегантное решение с применением того же самого полиморфизма порождает очень много дублированного кода. Но никого это особо не парит. Что характеризует.
Где это Вы в полиморфизме дублирование разглядели? Полиморфизм порожден как раз таки устранять дублирование, а не порождать его.
0
Заблокирован
26.11.2011, 01:30  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Вы порождаете сущность, которая дублирует функционал уже существующих сущностей.
Если в проекте присутствует одновременно и вектор, и велосипед, реализующий те же самые услуги - это ещё можно как то называть "дублированием функционала".
Но если в проекте присутствует только велосипед, или только вектор, то ни о каком дублировании уже нет и речи.

Цитата Сообщение от fasked Посмотреть сообщение
Где это Вы в полиморфизме дублирование разглядели? Полиморфизм порожден как раз таки устранять дублирование, а не порождать его.
Примеры дублирования кода:

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
struct A { int a;};
struct B { int a;};  //одна из них явно лишьняя
 
 
class Base
{
public:
    Base(){}
    virtual ~Base(){};
    virtual void View()=0;
};
 
class ConcreteA: public Base
{
public:
                     ConcreteA():Base(){}
    /*virtual */    ~ConcreteA() {}
    /*virtual*/      void View() { std::cout<< "ConcreteA\n";}
};
 
class ConcreteB: public Base
{
public:
                    ConcreteB():Base(){}
    /*virtual */    ~ConcreteB() {}
    /*virtual*/     void View() { std::cout<< "ConcreteB\n";}
};
 
//Самый популярный рецепт изготовления полиморфного семейства:
//1. Написать базовый интерфейс.
//2. Хардкорно копипастить его по всем потомкам.
 
//Причем зачастую, полиморф пользуют везде, где хотят 
//программировать в терминах интерфейсов. 
//даже там, где не требуется воспринимать абсолютно 
//разные типы объектов, как одну и туже сущность.

Хотя, если по задумке не требуется интерпретировать объекты типа ConcreteA и ConcreteB как одну и ту же сущность, то полиморфизм тут вообще не нужен будит. Тем не менее, они дублируют интерфейсы друг друга.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
26.11.2011, 01:36
Цитата Сообщение от Bers Посмотреть сообщение
Если в проекте присутствует одновременно и вектор, и велосипед, реализующий те же самые услуги - это ещё можно как то называть "дублированием функционала".
Как-то?
Цитата Сообщение от Bers Посмотреть сообщение
Но если в проекте присутствует только велосипед, или только вектор, то ни о каком дублировании уже нет и речи.
Я не понимаю, как средства стандартной библиотеки могут не входить в проект. Должны быть серьезные причины и не менее вразумительные обоснования на то, чтобы не пользоваться стандартной библиотекой языка.
Цитата Сообщение от Bers Посмотреть сообщение
Примеры дублирования кода
Кроме как "идиотскими" я эти примеры назвать никак не могу. То есть они показывают технологию полиморфизма как факта и не более. Где здесь полиморфизм с точки зрения красоты решения и архитектуры я не вижу и вряд ли кто-либо вообще видит.
0
Заблокирован
26.11.2011, 01:51  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Я не понимаю, как средства стандартной библиотеки могут не входить в проект.
Ну например, хэш-таблица, смартпоинтеры, аррэй не входят в поставку 2008 студии.

Цитата Сообщение от fasked Посмотреть сообщение
Кроме как "идиотскими" я эти примеры назвать никак не могу. То есть они показывают технологию полиморфизма как факта и не более.
Технология полиморфизма - это дублирование кода.
Весь полиморфный интерфейс дублируется подчастую, во всех потомках.

Даже более того, если нет необходимости интерпретировать абсолютно разные сущности, как одну, но хочется сделать им одинаковый интерфейс для удобства - это тоже уже дублирование кода. Ну и что в этом плохого?
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
26.11.2011, 01:57
Цитата Сообщение от Bers Посмотреть сообщение
Ну например, <...> аррэй не входят в поставку 2008 студии.
И это не повод в задаче такого уровня создавать собственный класс. Иными словами, это не повод не использовать std::vector.
Цитата Сообщение от Bers Посмотреть сообщение
Технология полиморфизма - это дублирование кода.
Весь полиморфный интерфейс дублируется подчастую, во всех потомках.
Само слово полиморфизм означает множество различных форм. Как может дублироваться то, что по определению разное? Переписывать надо не все методы, а только те, которые ведут себя по разному. И да, попробуйте-ка, написать все это дело без полиморфизма и тупо сравните количество кода.
0
Заблокирован
26.11.2011, 02:38  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Переписывать надо не все методы, а только те, которые ведут себя по разному.
Я вроде по русски пишу:

Цитата Сообщение от Bers Посмотреть сообщение
Весь полиморфный интерфейс дублируется подчастую, во всех потомках.
Цитата Сообщение от fasked Посмотреть сообщение
И да, попробуйте-ка, написать все это дело без полиморфизма и тупо сравните количество кода.
А я не пытаюсь избежать самого по себе дублирования кода. Меня не парит, если у меня будит десяток классов, каждый из которых будут иметь одноименные интерфейсы в своих заголовках.
Меня даже не парит, если они будут иметь одноименные методы + одноименные реализации этих методов, если это позволит избежать усложнения архитектуры.

И меня не парит, если некоторые из классов будут содержать одинаковые данные члены.

Главное требование - красивая и логичная архитектура. Решение задач в рамках заявленных требований.

Добавлено через 1 минуту
Цитата Сообщение от fasked Посмотреть сообщение
И это не повод в задаче такого уровня создавать собственный класс.
какого такого уровня?
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
26.11.2011, 23:39
Bers,
Весь полиморфный интерфейс дублируется подчастую, во всех потомках.
Адовый бред. Используется ОДИН интерфейс, а переопределяется только то, что нужно переопределить.

Во всех потомках (или почти во всех) должен быть РАЗНЫЙ код.
0
Заблокирован
26.11.2011, 23:49  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
Адовый бред. Используется ОДИН интерфейс, а переопределяется только то, что нужно переопределить.
Во всех потомках (или почти во всех) должен быть РАЗНЫЙ код.
То есть, сам по себе интерфейс за код не щитается, да?
Только реализация интерфейса?

А заголовки, наверное, компилятор сам за программиста пишет?
Он мысли программиста читает, и сам весь полиморфный интерфейс в потомков втыкает?
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
27.11.2011, 00:07
Лучший ответ Сообщение было отмечено как решение

Решение

Bers, Пример приведи. Я тебя не понимаю.

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
class Base
{
public:
   virtual void Foo()
   {
       std::cout << "Base" << std::endl;
   }
   virtual ~Base()
   {
   }
};
 
class Der1 : public Base
{
public:
   virtual void Foo()
   {
       std::cout << "Der1" << std::endl;
   }
   virtual ~Der1()
   {
   }
};
 
class Der2 : public Base
{
public:
   virtual ~Der2()
   {
   }
};
0
Заблокирован
27.11.2011, 00:30  [ТС]
ForEveR, ну я на самом деле уже догадываюсь, почему непонятка вышла.

1.
Класс имеет: прототипы методов, и реализацию этих прототипов (не всегда, и не для всех методов)

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

Ну так вот, список всех прототипов - это интерфейс класса.
а реализация этих прототипов - это реализация интерфейса класса.


То есть, под словом "интерфейс" лично я подразумеваю именно набор прототипов, а не набор прототипов + их реализации.

А вы походу, думаете, что интерфейс это и прототипы, и реализация.

2.
Код на с++ - это все символы из которых конструируется код в терминах с++, включая комментарии.

Заголовок класса - такой же полноценный код на с++, как и реализация этого класса.
И дублирование интерфейса (прототипов) полиморфного потомка является дублированием кода написанного на с++.

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

Одно из моих достижений в этой области - использование кодо-генераторов на макросах с автоматической "чисткой".

То есть, класс создаётся по некоторому шаблону, при помощи макроса.
Но такая запись крайне не читабельная, и ущербна в плане сопровождения.

Однако после первой же удачной компиляции срабатывает "чистка", и вместо "непонятного макроса" в файле оказывается полноценный класс, со всеми своими данными-членами и прочим.
Это тоже дублирование кода, но оно происходит автоматически, и не отбирает у программиста много времени.

При помощи макросов можно автоматизировать развертку целых архитектур. Очень быстро создавать заготовки-паттерны, и тп.

Например, с помощью кодо-генераторов на макросах удалось реализовать идиому "манипулятивных классов" - как одну из возможных замечательных альтернатив полиморфизму.

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

В данный момент, мне что бы создать очередную заготовку под манипулятор, нужно написать только три строчки макроса.
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
27.11.2011, 00:43
Bers, блин, ну обсуждали же уже пару месяцев назад всё это. Вы бред говорите, это уже на уровне фанатизма. То, о чём вы говорите, не подпадает под дублирование кода.
0
Заблокирован
27.11.2011, 00:50  [ТС]
Цитата Сообщение от silent_1991 Посмотреть сообщение
Bers, блин, ну обсуждали же уже пару месяцев назад всё это. Вы бред говорите, это уже на уровне фанатизма. То, о чём вы говорите, не подпадает под дублирование кода.
Я говорю, что дублирование кода на языке с++ никого особо не парит.
Но не нужно путать понятие "дублирование кода" с понятием "дублирование функционала"

А вы мне говорите, что дублирование кода на с++ к дублированию кода не относится.

То есть, копипаста интерфейсов - это типа не дублирование кода? Ну-ну
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
27.11.2011, 01:11
2
274 / 175 / 12
Регистрация: 14.03.2010
Сообщений: 501
27.11.2011, 01:38
Bers, в каком-то смысле вы правы. Вы только объясните, желательно на конкретных примерах, что вы предлагаете взамен полиморфизму. По-моему, всё равно должно получиться всё то же самое, только сложнее (т.к. средства, заложенные в язык, проще по определению).
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
27.11.2011, 13:04
Цитата Сообщение от Bers Посмотреть сообщение
какого такого уровня?
Я имел в виду ту тему, из которой этот разговор вышел.
Цитата Сообщение от Bers Посмотреть сообщение
Класс не обязан содержать реализацию своего интерфейса, и тогда его называют "чисто-абстрактным классом".
Правда? Я то всегда думал, что абстрактный класс - тот, который имеет хотя бы один чисто виртуальный метод.

Цитата Сообщение от Bers Посмотреть сообщение
То есть, класс создаётся по некоторому шаблону, при помощи макроса.
Еще бы она была не ущербна. Мне ведь не нужно копировать вообще все прототипы функций.
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <memory>
#include <iostream>
 
class Base {
public:
   virtual ~Base() = 0;
 
   virtual void foo() {
      std::cout << "base foo " << std::endl;
   }
   
   virtual void bar() {
      std::cout << "base bar " << std::endl;
   }
   
   virtual void quz() {
      std::cout << "base quz " << std::endl;
   }
};
 
Base::~Base() { }
 
class Derived1 : public Base {
public:
   virtual ~Derived1() { 
   }
   
   virtual void quz() {
      std::cout << "derived 1 quz " << std::endl;
   }
};
 
class Derived2 : public Base {
public:
   virtual ~Derived2() { 
   }
   
   virtual void bar() {
      std::cout << "derived 2 bar " << std::endl;
   }
};
 
void foo(Base *p) {
   p->quz();
   p->foo();
   p->bar();
}
 
int main() {
   Base *p1 = new Derived1();
   Base *p2 = new Derived2();
      
   foo(p1);
   foo(p2);
   
   delete p1;
   delete p2;
   
   return 0;
}
Ну и можно сказать, что методов в базовом классе может быть вообще-то больше чем два или три. И они могут быть гораздо сложнее.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.11.2011, 13:04
Помогаю со студенческими работами здесь

Дублирование базы , или дублирование информациии
Доброго времени суток ! Поставлена задача: мне нужно либо при изменении или добавлении данных делать копию базы, и так каждый раз с ее...

Абстракции
Мои работы в стиле абстракций. Работа выполненная несколько месяцев назад.

Неопределенность в абстракции
Добрый день. Есть класс A от которого производится класс В и С. У этих классов есть общий метод f1(). у класса B не...

Абстракция, уровни абстракции
Как понять это? Может кто-нибудь объяснить более доступным и понятным языком нежели википедия?

Entity Framework и абстракции
Можно сказать &quot;новичковый&quot; вопрос :) Есть сущности, созданные из базы данных. Database First. К примеру, код только как пример, в...


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

Или воспользуйтесь поиском по форуму:
20
Закрытая тема Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru