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

Использование инструмента friend в проекте

24.06.2015, 18:52. Показов 5912. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день,

я считаю, что дать полный доступ классу на все внутренности - это нарушение инкапсуляции, пораждении дыри через которую можно не то, что ранить - а убить. Человек правит свой класс B которому дали полный на класс А. Всё работает - всё супер. Компилирует всё работает. Но в каких-то случаях оно падает. К примеру (синтаксический пример) в классе А переменная x не может быть 13. А владелец класса В напрямую пишит: classA->x = 13; Более того закрепить очередную внешнюю связь дял класса это разве SOLID одобрено?)

Цитата Сообщение от DrOffset Посмотреть сообщение
Еще раз подчеркну, что все вышесказанное не относится непосредственно к пользе или вреду от friend - это совершенно отдельный разговор.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.06.2015, 18:52
Ответы с готовыми решениями:

Использование инструмента Авторазмер в Компас 3D 17
Привет, ребята. Я - новичок в компасе. Только недавно стал в нем делать первые шаги. У меня возник следующий вопрос. При работе с 3D...

Использование инструмента Элемент выдавливания в Компас 3D 17
Привет, ребята. Обращаюсь к Вам за помощью. Проблема в следующем - мне нужно создать фигуру, похожую на зубчатое колесо. Я создаю...

Перегрузка операторов, friend или нет friend?
Всем здравствуйте. Есть такой вопрос: при перегрузке операторов в классе(пусть будут + и = (вообще неважно, за исключением потока)) как и...

21
76 / 76 / 32
Регистрация: 14.04.2014
Сообщений: 408
24.06.2015, 19:14
а что мешает обернуть все в методы, где проверять
C++
1
if(x==13) return;
?
0
15 / 15 / 3
Регистрация: 04.02.2013
Сообщений: 124
24.06.2015, 19:18
А как тогда реализовывать отношения "один ко многим"? Тот же пример из Праты, класс телевизора и класс пульта дистанционного управления, ведь один пульт может управлять несколькими ящиками. Тут без друзей либо нужно открывать закрытые члены, что опять же убивает инкапсуляцию, либо писать какие-то хитрые громоздкие классы для такого рода отношений, менее понятные и менее абстрактные. А если в телевизоре только 12 каналов, а на пульте управления 13 кнопок с каналами, то ничего страшного, пусть телевизор сам решает, что ему делать в случае сигнала 13 канала с пульта. Можно и исключения, наверное, использовать. ИМХО

Добавлено через 1 минуту
Кстати, как такие отношения реализованы в других языках ООП?

Добавлено через 2 минуты
Кстати, друзья даже менее убивают инкапсуляцию, чем просто вскрытие закрытого поля. Если поле будет в открытом разделе, то канал и кофеварка сможет переключить.
0
76 / 76 / 32
Регистрация: 14.04.2014
Сообщений: 408
24.06.2015, 19:22
я прочел ту тему, и понял о чем речь.
Думаю, что этот оператор включен в язык для расширения функционала, и не является мастхэв.
Возможно он сделан для того, чтобы можно было одни и теже данные делить на несколько классов, которые в 1 обьеденить никак нельзя.
Тогда и получается структура вида 1класс с набором данных и несколько френдов оперирующих этими данными, но в таком случае проверки на корректность чтения/записи остаются за самими классами.
ПОлучается сильная связанность к тому же.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
24.06.2015, 19:35  [ТС]
То, что я вижу - 95% людей используют friend потому, что ТАК ЛЕГЧЕ.
0
15 / 15 / 3
Регистрация: 04.02.2013
Сообщений: 124
24.06.2015, 19:42
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
То, что я вижу - 95% людей используют friend потому, что ТАК ЛЕГЧЕ.
Тогда странно, что они вообще пишут на плюсах.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
24.06.2015, 19:50  [ТС]
ну написать 100500 геттеров и толковый интерфейс для работы с классом дольше, чем одной строкой дать "алл инклюдед в отелях Турции"
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
24.06.2015, 21:11
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Раз уж меня сюда процитировали, то мне, видимо, необходимо ответить.
Как я уже говорил, friend - это очень мощный механизм. И из-за этого его очень просто использовать неправильно.
Обычный довод, который используют т.н. "противники" - это нарушение инкапсуляции. Я приведу несколько примеров, когда friend не только не нарушает инкапсулцию, но и усиливает ее.

Пример 1: Вариант на тему "Порождающие классы".
Предположим, что у нас есть классы, объекты которых не разрешено создавать кому попало. Заведем себе класс, который, будет порождать наши объекты. Как же запретить остальным это делать "by design"? Один из способов - это поместить конструкторы наших классов в private, а создающую функцию класса-строителя определить другом:
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
class Base {};
 
class Builder
{
public:
    template <typename T>
    std::unique_ptr<T> create() const
    {
        return std::unique_ptr<T>(new T());        
    }
};
 
class A : public Base
{
    friend std::unique_ptr<A> Builder::create<A>() const;
    
    A() {}
};
 
class B : public Base
{
    friend std::unique_ptr<B> Builder::create<B>() const;
    
    B() {}
};
http://rextester.com/TPZH44403

Пример 2: Интераторы.
У нас есть класс, которому нужен итератор. Внутренней структуры мы предоставлять не хотим., но итератору необходимо работать с некоторыми внутренними данными.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Iterator
{
};
 
class Container
{
    friend class Iterator;
public:
    Iterator begin()
 
private:
    // Список методов, которые мы не хотим показывать кому попало
    int getCount() const; 
    
};
Эта идея наглядно продемонстрирована в реализации классов стандартной библиотеки vector, bitset, list и др. Можно полюбопытствовать в стандарте начиная с параграфа 20.6.

Пример 3: Функция относится к интерфейсу класса, но требует левым операндом другой объект.
Никогда не задумывались, почему операторы !=, ==, и << >> очень часто реализуют как дружественные функции? Наш класс имеет некоторые данные, которые должны быть сравнены, независимо от того, слева или справа от оператора != или == он находится. Иногда так бывает, что класс дает геттеры для всех данных, которые можно так сравнить, а что, если нет? Заводить открытый геттер для внутренних данных, только ради того, чтобы использовать его в функции сравнения и не делать ее friend? Вот где настоящее нарушение инкапсуляции. В интерфейсе класса появился открытый метод к внутренним данным, которые не должны быть видны, но теперь их может использовать кто угодно!
В этом вопросе сошлюсь также на правило 19 замечательной книжки Скотта Мейерса "Эффективное использование С++". Очень важно здесь учитывать, что этот пример не призывает использовать friend везде, где требуется перегрузка операторов, а лишь там, где это действительно необходимо.

Пример 4, риторический: "А чего он, собственно, нарушает?"
Итак, класс сам определяет какую функцию или класс сделать другом. Ответственность на этом полностью лежит на разработчике класса. Функцию, объявленная другом, точно так же становится частью интерфейса, как и любой метод. С этой точки зрения ничего не меняется
C++
1
2
3
4
5
6
7
8
9
10
class A 
{
public:
    void foo() const { }
    static void bar(A const &) { }
 
    friend void bar1(A const &) { } // bar1 не хуже функций foo и bar в смысле инкапсуляции
    friend void foo1(A const &); // foo1 тоже
 
};
Опять же, воспринимать этот пример, как призыв использовать friend везде - не нужно. Это лишь демонстрация того, что инкапсуляция не пострадала. Проблема замены метода класса на friend функцию лежит не в плоскости инкапсуляции, а в вопросе целесообразности. Дизайн программы - вот что должно быть отправной точкой. Оправданность. Отошлю еще раз к финалам правил 18 и 19 упомянутой выше книги. Либо к 23-24 в новом издании.

Пример 5, не мой: Этот пример можно посмотреть в книге "Новые сложные задачи на С++" Герба Саттера (задача 8).
______
Все вышенаписанное не стоит воспринимать как призыв использовать friend везде (чем иногда грешат советы по перегрузке операторов здесь, на форуме). Можно гораздо больше текста написать о вреде, который может быть нанесен необдуманным использованием friend. Но это уже сделали вместо меня, гораздо более авторитетные люди. Посему, предлагаю всем сомневающимся открыть правило 44 книги "Стандарты программирования на С++", там можно найти популярные причины отказа от friend, а также алгоритм выбора варианта определения функции как части интерфейса (свободная функция, функция-член и свободная функция-друг).
______
Завершить хотелось бы цитатой, которая должна быть эпиграфом к этому посту:
I have never been able to see the recurring assertions that a friend declaration "violates encapsulation" as anything but a combination of ignorance and confusion with non-C++ terminology.
-- Bjarne Stroustrup, "The Design and Evolution of C++"
Тройка ссылок по теме (с разнообразными мнениями):
http://stackoverflow.com/quest... as-friends
http://stackoverflow.com/quest... r-function
http://stackoverflow.com/quest... -the-prope
16
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
24.06.2015, 21:20
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
я считаю, что дать полный доступ классу на все внутренности - это нарушение инкапсуляции, пораждении дыри через которую можно не то, что ранить - а убить.
Ну, мы закрываем класс ровно настолько, чтобы абстрагироваться от тех объектов, которые не входят в систему, в которой его объекты функционируют, но с объектами-то своей системы он должен взаимодействовать, а некоторые из них бывают тесно связаны между собой.
Вам надо Страуструпа почитать, он в своей книжке доходчиво объясняет для чего нужны классы-друзья, подчеркивая, что их нужно применять только для отражения тесно связанных концепций.
Ну, тот же пример оператора умножения матрицы на вектор, который должен иметь доступ к обоим этим классам.
Еще одна причина – неявные преобразования типов. Бинарные операторы с таким преобразованием должны быть или глобальными функциями, или дружественными, например, будь бинарные операторы комплексных чисел членами класса complex, мы не смогли бы к целому числу прибавить комплексное или к комплексному действительное.
2
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
24.06.2015, 21:35
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
То, что я вижу - 95% людей используют friend потому, что ТАК ЛЕГЧЕ.
вообще friend чаще всего используется для функций перегрузки операторов со сторонним типом. к примеру чтобы сделать operator * (float f, TVector& v); и operator * (TVector& v,float f); А вместо friend классов таки лучше использовать свойства с сеттерами и геттерами.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.08.2015, 00:03  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Пример 1:
Я бы хотел еще уточнить, ведь если использовать данный подход - то необходимо таскать весь перечень классов ( их headers files - в моей случаи это тип юнита).
C++
1
A::createUnit<Archer>(); // Archer должен быть определён тут
Следовательно более приемливо использовать
C++
1
2
A::createUnit(const eUnitID& enumID);
A::createUnit(const std::string& unitID);
Но тогда внутри имея enum или string не вызвать private method свой create<T>();


Как оптимизировать этот момент под ваш пример "friend factory"
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.08.2015, 00:53
rikimaru2013, запросто, можно заменить тип на enum id.
Кликните здесь для просмотра всего текста
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
61
62
63
64
65
66
67
#include <iostream>
#include <memory>
 
// Builder.h
 
enum ClassesEnum 
{
    AClassId
  , BClassId
};
 
class Base {};
 
class Builder
{
public:
    template <ClassesEnum Id>
    std::unique_ptr<Base> create() const;
};
 
// Builder.cpp
 
/* include a.h */
class A : public Base
{
    friend std::unique_ptr<Base> Builder::create<AClassId>() const;
    
    A() {}
};
/* include b.h */
class B : public Base
{
    friend std::unique_ptr<Base> Builder::create<BClassId>() const;
    
    B() {}
};
 
#include <boost/mpl/map.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/at.hpp>
 
namespace mpl = boost::mpl;
 
using builder_types = mpl::map<
      mpl::pair<mpl::int_<AClassId>, A>
    , mpl::pair<mpl::int_<BClassId>, B>
>;
 
template <ClassesEnum Id>
std::unique_ptr<Base> Builder::create() const
{
    using type = typename mpl::at<builder_types, mpl::int_<Id>>::type;
    
    return std::unique_ptr<Base>(new type());        
}
 
// добавим явное инстанцирование для того, чтобы работало разделение на h и cpp
template std::unique_ptr<Base> Builder::create<AClassId>() const; 
template std::unique_ptr<Base> Builder::create<BClassId>() const; 
 
int main()
{
    Builder bld;
    
    std::unique_ptr<Base> p1 = bld.create<AClassId>();
    std::unique_ptr<Base> p2 = bld.create<BClassId>();
}
http://rextester.com/BOOO5550

Решение конечно не из разряда очевидных, но поддерживать его относительно легко. Добавление новых типов осуществляется только в одном файле. Можно и другой, более динамический способ придумать:
Кликните здесь для просмотра всего текста
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
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <memory>
 
// Builder.h
 
enum ClassesEnum 
{
    AClassId
  , BClassId
};
 
class Base {};
 
#include <map>
 
class Builder
{
public:
    template <typename T>
    struct Make
    {
        std::unique_ptr<Base> operator()() const
        {
            return std::unique_ptr<Base>(new T());
        }
    };
 
    Builder();
    
    std::unique_ptr<Base> create(ClassesEnum Id) const;
    
private:
    std::map<ClassesEnum, std::function<std::unique_ptr<Base>()>> builders_;
};
 
// Builder.cpp
 
/* include a.h */
class A : public Base
{
    friend class Builder::Make<A>;
    
    A() {}
};
/* include b.h */
class B : public Base
{
    friend class Builder::Make<B>;
    
    B() {}
};
 
Builder::Builder()
    : builders_{ { AClassId, Make<A>() }, { BClassId, Make<B>() } }
{ }
 
std::unique_ptr<Base> Builder::create(ClassesEnum id) const
{
    auto it = builders_.find(id);
    if(it != builders_.end())
    {
        return it->second();
    }
    return std::unique_ptr<Base>();
}
 
int main()
{
    Builder bld;
    
    std::unique_ptr<Base> p1 = bld.create(AClassId);
    std::unique_ptr<Base> p2 = bld.create(BClassId);
}
http://rextester.com/HOTT74759

Опять же, это не все варианты. Но я уже устал сегодня.

Добавлено через 9 минут
rikimaru2013, небольшая поправка для второго примера, а то сейчас прилетит кто-нибудь с дикими воплями, что я нарушаю инкапсуляцию.
В определении класса builder в h нужно оставить только объявление класса make, чтобы его невозможно было использовать откуда-то еще кроме, кроме builder.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class Builder
{
public:
    template <typename T>
    struct Make;
        
    Builder();
    
    std::unique_ptr<Base> create(ClassesEnum Id) const;
    
private:
    std::map<ClassesEnum, std::function<std::unique_ptr<Base>()>> builders_;
};
А определение класса перенести в builder.cpp:
C++
1
2
3
4
5
6
7
8
template <typename T>
struct Builder::Make
{
    std::unique_ptr<Base> operator()() const
    {
        return std::unique_ptr<Base>(new T());
    }
};
Вот код после изменений: http://rextester.com/AZHEF50728
2
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.08.2015, 13:57  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
enum id
По суте добавления нового юнита в enum приведёт к, практически, полной пересборке проекта, что может сказаться на время разработки проекта. Если использовать строковый ключ для определения какого юнита необходимо создать, то это приведёт к чуть длительному процессу сравнения строк при поиске по вектору, но добавления новго класса не будет влиять на другие.

Можете скзаать ваше мнение по этому поводу - чтобы вы использовали?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.08.2015, 15:18
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
По суте добавления нового юнита в enum приведёт к, практически, полной пересборке проекта,
Ни в коме случае. Если enum наращивать правильно (добавлять новые значения в конце, не трогая предыдущие), то не будет проблем. Но определенная опасность все-таки есть, если кто-то не будет следовать этому правилу.

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Можете скзаать ваше мнение по этому поводу - чтобы вы использовали?
Абстрактно сказать нельзя, зависит от задачи. Насколько часто будет эта фабрика вызываться, какой длины ключи, насколько их много и т.п. Конечно строки - это понятнее и удобнее. Если нет каких-то особых ограничений, то можно остановиться на них, как на варианте по умолчанию.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.08.2015, 15:39  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Ни в коме случае
Через пару минут проверю. Как я помню и уверен, если сделать любые изменения в header file где enum вплоть до пробела, то перекомпилируются все файлы где подключён этот header
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.08.2015, 15:44
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Как я помню и уверен, если сделать любые изменения в header file где enum вплоть до пробела, то перекомпилируются все файлы где подключён этот header
Это ваша система сборки за этим следит. Но это не значит, что оно будет так везде
Вообще конечно отсутствие перекомпиляции приводит к нарушению ODR, но в данном случае оно достаточно невинно.

Добавлено через 2 минуты
rikimaru2013, еще можно избавиться от единого enum, а вместо этого определять уникальную константу прямо в новом юните. Становится сложнее контролировать уникальность, но вот перекомпиляции уже не будет точно, т.к. каждая константа в своем отдельном файле.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.08.2015, 15:51  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
определять уникальную константу прямо в новом юните
C++
1
2
3
4
5
6
7
8
9
// Archer
enum
{
    MY_UNIQUE_ID = 188,
};
int getUnitId() const
{
    return MY_UNIQUE_ID,
}
Так чтоле? Отсюда надо знать при вызове createUnit(188) <- откуда это знать?) Записать на бумажке чтоле
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
07.08.2015, 15:57
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Так чтоле? Отсюда надо знать при вызове createUnit(188) <- откуда это знать?) Записать на бумажке чтоле
Можно и так. Можно вообще отдельный файл завести. Есть например unit_1.h, где определен класс. А есть unit_1_id.h, где сидит его id. Если хочешь создать объект, то подключаешь только unit_1_id.h.
Вообще тут нет правильных и неправильных вариантов. Ты сейчас похоже хочешь найти серебряную пулю, а ее нет. Взвешивай достоинства и недостатки различных примеров применительно к своему проекту. Это путь к истине. Я могу только вариант предложить, а подходит тебе он или нет - решай сам.
1
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
22.11.2022, 20:34
Цитата Сообщение от DrOffset Посмотреть сообщение
new T()
а почему не std::make_unique ?

Добавлено через 5 минут
признак хорошего тона?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
22.11.2022, 20:35
Цитата Сообщение от _stanislav Посмотреть сообщение
а почему не std::make_unique
Потому что код для С++11.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.11.2022, 20:35
Помогаю со студенческими работами здесь

Использование библиотек в проекте AS
Подскажите как использовать библиотеку. у меня есть некая библиотека lib.jar (внутри определенное количество file.java и file.class) ...

Использование в проекте аккумулятора.
Есть действующий проект. Серия блоков управления станками. Блоки работают уже несколько лет и отлично себя зарекомендовали. В этом проекте...

Использование интерполяции в проекте
Здравствуйте. Есть набор данных: T1 = 1392 T2 = 1395 T3 = 1460 T4 =1493 T5 = 1540 T6 = 1562 T7 =1579

Использование MongoDB в С++ проекте
Всем привет! Хотел бы получить опыт работы с MongoDB, но не знаю с чего начать (каким образом подключить ее к проекту и какие у нее...

Использование фреймворков в проекте
Изучая PHP наткнулся на такое чудо как фреймы, и сразу возникли вопросы: 1)Как их изучать? Почитав документацию к сожалению ничему не...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru