С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/18: Рейтинг темы: голосов - 18, средняя оценка - 4.67
 Аватар для Kant
37 / 37 / 18
Регистрация: 15.05.2013
Сообщений: 236

Параметры по-умолчанию в виртуальных функциях

15.11.2016, 20:37. Показов 3675. Ответов 42
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Подскажите, это ведь UB ?

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
#include <iostream>
 
class Base {
    int a;
 
public:
    Base() : a(1) {}
    explicit Base(const int aa) : a(aa) {}
 
    virtual void foo(int a = 42) {
        int c = a;
        std::cout << c << "\n";
    }
 
};
 
class Derived : public Base {
    int b;
 
public:
    Derived() : b(2) {}
    explicit Derived(const int bb) : b(bb) {}
 
    void foo(int b = 666) override {
        int c = b;
        std::cout << c << "\n";
    }
 
};
 
int main () {
    Base *derived = new Derived;
    derived->foo();
    return EXIT_SUCCESS;
}

Я понимаю, что при пустом foo() сработал бы вариант из Derived, но вот с добавлением значений по умолчанию хз.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.11.2016, 20:37
Ответы с готовыми решениями:

О виртуальных функциях
Читаю у Страуструпа 3 издание по с++ 12.2.6. Виртуальные функции и не много не догоняю что он имеет ввиду процитирую: &quot;Для того...

Значение по умолчанию в функциях
Пишу int __fastcall TFMain::Tets(int x=2) { return x; } Компилятор выдает: Default argument value redeclared for parameter 'x'...

Значения по умолчанию в функциях С++
Возникла проблема на пустом месте, а именно с параметрами по умолчанию, чтобы не передавать в функцию &quot;лишнии&quot; значения. Имеем...

42
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
15.11.2016, 20:45
Лучший ответ Сообщение было отмечено Kant как решение

Решение

Цитата Сообщение от Kant Посмотреть сообщение
Подскажите, это ведь UB ?
Нет, это не UB, просто параметры по-умолчанию
компилятор проставит еще при компиляции,
поэтому параметр, заданный по-умолчанию
определяется исходя из типа указателя.
Как следствие, будет вызван foo из Derived,
но с параметром по-умолчанию, заданным в Base.
3
 Аватар для Kant
37 / 37 / 18
Регистрация: 15.05.2013
Сообщений: 236
15.11.2016, 20:54  [ТС]
Croessmah, спасибо, ты как всегда хорошо объяснил. Можешь немного подробнее почему
значение по умолчанию берется исходя из типа указателя. Как-то не ложится
это у меня в голове.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
15.11.2016, 21:15
Лучший ответ Сообщение было отмечено Kant как решение

Решение

Цитата Сообщение от Kant Посмотреть сообщение
Можешь немного подробнее почему значение по умолчанию берется исходя из типа указателя.
Всё просто на самом деле.
В этом месте derived->foo(); компилятор
должен проверить и построить легальный код для вызова.
Он прекрасно видит, что есть один вариант foo,
который можно использовать таким образом (вызов без указания параметра),
и ему нужно здесь передать в функцию аргумент:
derived->foo(параметр-заданный-по-умолчанию);
Внимание, у нас этап компиляции, компилятору
неизвестно какой там реально будет тип в памяти.
Поэтому сначала кратенько напомню,
что есть статический и динамический типы.

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

Статический тип - это тип выражения, который определяется
в результате анализа программы без учета выполнения семантики.
В нашем случае в выражении derived->foo();
derived - это указатель на объект типа Base.

То, что в памяти при derived->foo();
окажется объект типа Derived
будет известно только во время выполнения,
Во время компиляции же компилятору здесь вообще не может быть известно,
какой реально тип имеет объект, на который указывает derived,
но код вызова он построить должен, так что у него нет другого выбора,
кроме как взять параметр по-умолчанию исходя из статического типа,
и впихнуть его сюда т.е. параметр будет взят из Base::foo,
и будет построен код аналогичный derived->foo(42);.
9
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.11.2016, 21:38
Цитата Сообщение от Croessmah Посмотреть сообщение
есть статический и динамический типы
Понятное дело, не поверил вам, полез в стандарт, а там и вправду есть понятие динамический тип. И это в статически типизироемом языке. Жуть. Как только не обзовут ранее и позднее связывание ...
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
15.11.2016, 21:43

Не по теме:

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
не поверил вам
И какой тогда был смысл читать пост,
если всё равно не верите прочитанному?
- Я ему не верю, но всё равно буду читать бред, который он пишет.:D



Добавлено через 3 минуты
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
И это в статически типизироемом языке.
Эмм... динамические типы - основная идея динамического полиморфизма,
который в C++ реализуется с помощью виртуальных функций.
И вот как раз если бы язык был динамически типизируемый,
то параметры бы брались уже во время выполнения, но увы.
Да и виртуальные функции тогда были бы не нужны.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
15.11.2016, 21:56

Не по теме:

Цитата Сообщение от Croessmah Посмотреть сообщение
И какой тогда был смысл читать пост, если всё равно не верите прочитанному?
Доверяй, но проверяй :)



Croessmah, я только прицепился к слову "динамический тип".
Меня вирт методы в С++ весьма доставляют)) По моей логике, тип то
один T* - и меняется только поведение.
Как там пишут "один интерфейс - множество реализаций". Взглянув на
Foo* fn(), я точно знаю, что там тип Foo* -
а то что поведение будет зависеть от наличие полиморфизма -
это уже детали реализации на которые программист не обращает внимание.
Пишите код и думаете о всех последствиях полиморфного вызова? Нет.
Вы точно знаете по названию метода и возвращаемому значению, что
произойдет. А будет это под музыку, или по-пьяне - это уже детали
чёрного ящика.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
15.11.2016, 22:08
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Пишите код и думаете о всех последствиях полиморфного вызова?
Обычно, я думаю о последствиях любого вызова.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
16.11.2016, 00:00
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
полез в стандарт, а там и вправду есть понятие динамический тип
Ну, в новом Липпмане уже есть.

Добавлено через 1 минуту
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
динамический тип. И это в статически типизироемом языке
Какое-то тут противоречие есть...

Добавлено через 7 минут
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
По моей логике, тип то
один T* - и меняется только поведение
Ну почему же? Этому указателю может быть присвоен указатель на объект любого потомка класса T, который и по размеру может быть больше, и членов-данных в нем может быть больше. Так что не только поведение, но и состояние может отличаться от объекта статического типа.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
16.11.2016, 00:32
Цитата Сообщение от Mr.X Посмотреть сообщение
Этому указателю может быть присвоен указатель на объект любого потомка класса T,
Не правда. Этому указателю может быть присвоен только адресс. И размер указателя всегда будет один и тот же. Зачем вы путаете? И имея на руках указатель Т* можно чётко сказать, какие методы можно вызвать - других там нету и не будет.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
16.11.2016, 01:21
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
И размер указателя всегда будет один и тот же
Ну, я имел в виду размер объекта, на который этот указатель ссылается. Хотя ограничения таковы, что через этот указатель мы можем добраться только до его виртуальных компонентов, так что вы тут правы насчет поведения, хотя указатель может таки указывать на объекты разных типов.
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
16.11.2016, 01:27
Цитата Сообщение от Mr.X Посмотреть сообщение
Какое-то тут противоречие есть...
Это смотря как посмотреть.
Все телодвижения делаются исходя из статического типа.
А уж что там пользователь наворотил - дело уже совсем другое.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
16.11.2016, 01:27
Цитата Сообщение от Croessmah Посмотреть сообщение
Как следствие, будет вызван foo из Derived,
но с параметром по-умолчанию, заданным в Base.
Croessmah, спасибо. Удивительный факт. Я думал, что параметр по умолчанию сокращает запись 2-х перегрузок, но оказывается это не так.
В связи с этим вопрос. Получается, что параметр по умолчанию, это грабли для ленивых? Ведь если перегрузить явно, то проблем не возникает?
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
74
75
76
77
78
79
80
81
82
83
#include <iostream>
 
class Base {
    int a;
 
public:
    Base() : a(1) {}
    Base(const int aa) : a(aa) {}
 
    virtual void foo(int a = 42) {
        int c = a;
        std::cout << c << "\n";
    }
 
};
 
class Derived : public Base {
    int b;
 
public:
    Derived() : b(2) {}
    Derived(const int bb) : b(bb) {}
 
    void foo(int b = 666) {
        int c = b;
        std::cout << c << "\n";
    }
 
};
class Bas {
    int a;
 
public:
    Bas() : a(1) {}
    Bas(const int aa) : a(aa) {}
 
    virtual void foo() {
        int c = 42;
        std::cout << c << "\n";
    }
     virtual void foo(int a) {
        int c = a;
        std::cout << c << "\n";
    }
 
};
 
class Deriv : public Bas {
    int b;
 
public:
    Deriv() : b(2) {}
    Deriv(const int bb) : b(bb) {}
 
    void foo() {
        int c = 666;
        std::cout << c << "\n";
    }
 
    void foo(int b) {
        int c = b;
        std::cout << c << "\n";
    }
 
};
 
int main () {
    Base *derived;
    int a;
    std::cout<<"a-a-a!!! ";
        std::cin>>a;//1
            derived = a?  new Derived : new Base;   
                derived->foo();//42
 
    std::cout<<std::endl;
 
Bas *deriv;
    deriv = a?  new Deriv : new Bas;    
        deriv->foo();//666
            std::cin.get();
                std::cin.get();
    return EXIT_SUCCESS;
}
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
16.11.2016, 01:37

Не по теме:

Цитата Сообщение от Mr.X Посмотреть сообщение
так что вы тут правы насчет поведения
:yahoo: молодой!



Цитата Сообщение от Mr.X Посмотреть сообщение
хотя указатель может таки указывать на объекты разных типов
Ну и тут могу поспорить) Указатель хранит адрес на определённый тип. При присвоение в auto тип будет определён однозначно ведь.

Думаю вы прибегаете к термину "динамический тип", который описали выше. Но мне эта "динамика" больше напоминает поведение, чем физический свойства.

Добавлено через 1 минуту
Цитата Сообщение от IGPIGP Посмотреть сообщение
Получается, что параметр по умолчанию, это грабли для ленивых?
Все вариации параметров по умолчанию это вариант для ленивых написать нормальную перегрузку или делигирование. Наведёте пример, где параметр по умолчанию must-have - дам мороженое!
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
16.11.2016, 01:46
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Все вариации параметров по умолчанию это вариант для ленивых написать нормальную перегрузку или делигирование. Наведёте пример, где параметр по умолчанию must-have - дам мороженое!
Я не спорю. Просто задал вопрос. Интересно что Саша скажет.
Я всегда думал, что если при вызове шаблона вариант кода определяется на стадии компиляции, то при вызове виртуального метода на указателе базового класса, компилятор вынужден генерировать все ветви исполнения ( с любыми наследниками, и в.т.ч. базового (если он не абстрактный)). А фактический вызов в рантайме это переход на ветвь которая определяется по скрытому логическому блоку анализирующему RTTI. То есть, нет в действительности, динамического типа. Так мне казалось.
А сейчас что-то не могу переварить увиденное. Нужно время и чтиво. Видимо работа с в-методами через в-тэйбл не вошли в мой тэйбл до конца.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
16.11.2016, 01:52
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Ну и тут могу поспорить) Указатель хранит адрес на определённый тип
Ну, тут вы смешиваете тип указателя и тип объекта, на который он указывает. Тип указателя - указатель на базовый класс, а тип объекта может другим быть.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
16.11.2016, 01:59
Цитата Сообщение от Mr.X Посмотреть сообщение
Тип указателя - указатель на базовый класс, а тип объекта может другим быть.
Но указатель хранит адрес на тип который носит на щите. Он не знает на что он смотрит, но уверен что на Base. Вся "магия" в неявном преобразовании при присвоении или при инициализации параметра при передаче. Главное, - в неявном преобразовании. После преобразования он хранит адрес на тот тип, на который он объявлен хранить адрес.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
16.11.2016, 02:07
Цитата Сообщение от Mr.X Посмотреть сообщение
Ну, тут вы смешиваете тип указателя и тип объекта, на который он указывает.
Я явно указываю просто, что в типе указателя явно указан
тип объекта на который он ссылается. Поэтому я не путаю.
Возможность потомков записать себя в указатель на родительский
класс, это свойство от наследование. При этом компилятор всем
сердцем верит, что там объект типа Base* и
явно вам будет об этом говорить на протяжении всего
программирования. После компиляции нету уже понятия тип и
только адрес и операции.

Еще раз) Имея указатель T*, мы имеем именно
адрес на объект типа Т. То, что этот
объект наделён полиморфным свойством от Полиморфизма за
счёт определённых действий, не в коем случаи не говорит нам,
что мы можем получить с указателя Т*, что-то
другое.

Разименнуем указатель, который имеет другой "динамический" тип
получим по факту славную срезку со всеми вытекающими. Во вторых,
при работе с вирт методами будет механизм позднего связывания. А во всем
другом - этот указатель ничем не отличается от других которые
"действительно" указывают на Base*. Заметьте
я специально взял слово действительно в кавычки, потому что
все указатели T* хранят адрес на объект типа Т

P.S. Пишу как hoggy, спорю со всеми как hoggy,
вот бы еще знаний и опыта как у него) А то пока с моими 19 месяцами
в С++ - спорить аргументировано на некоторые темы тяжело )
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
16.11.2016, 02:19
Лучший ответ Сообщение было отмечено Kant как решение

Решение

Цитата Сообщение от IGPIGP Посмотреть сообщение
Ведь если перегрузить явно, то проблем не возникает?
Если перегрузить, то вызов ptr->foo() и ptr->foo(42)
приведут к вызову разных виртуальных функций.
Собственно, всё это можно "на пальцах" описать на другом примере:
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
//g++  4.9.3
 
#include <iostream>
 
 
 
struct Base
{
    void foo(int x)
    {
        std::cout << "Base::foo(" << x << ")" << std::endl;
    }
    
    virtual void bar(int x = 42) 
    {
        std::cout << "Base::bar(" << x << ")" << std::endl;
    }
    
    void zoo()
    {
        std::cout << "Base::zoo()" << std::endl;
    }
};
 
 
struct Derived : Base
{
    void foo(int x)
    {
        std::cout << "Derived::foo(" << x << ")" << std::endl;
    }
    
    void bar(int x = 666) 
    {
        std::cout << "Derived::bar(" << x << ")" << std::endl;
    }
    
    virtual void zoo()
    {
        std::cout << "Derived::zoo()" << std::endl;
    }
};
 
 
 
int main()
{
    Derived obj;
    Base *pObj = &obj;
    
    pObj->foo(10);//П1
    pObj->bar();//П2
    pObj->zoo();//П3
}
http://rextester.com/TPJZ59696
Base::foo(10)
Derived::bar(42)
Base::zoo()
В контексте данного кода, наверное,
можно рассказать немного о раннем и позднем связывании.
Упростим всё донельзя.
Компилятор всегда строит код основываясь на статических типах.
Вопрос лишь в том, как именно он его построит.

Раннее связывание - заранее известно что и как будет, связывание произойдет во время компиляции.
Позднее связывание - заранее неизвестно что к чему и связывание произойдет во время выполнения.

Но код и для того и для другого строится всё равно при компиляции.

Смотрим на код выше (описываю немного не по порядку).
Вызов в строке "П1" - pObj->foo(10);.
Функция-член foo не виртуальная,
поэтому будет использовано раннее связывание.
Компилятор возьмет и пропишет код вызова Base::foo с заданным параметром,
независимо от того, на что на самом деле указывает указатель.

Вызов в строке "П3" - pObj->zoo();.
В классе Derived функция-член zoo виртуальная.
Однако компилятор ничего не знает о динамическом типе объекта,
на который указывает указатель pObj.
В классе Base функция-член zoo не виртуальная,
поэтому компилятор, основываясь на статическом типе,
делает раннее связывание, строя код для вызова Base::zoo.

Вызов в строке "П2" - pObj->bar();.
У нас же нет функции-члена bar без параметров.
Зато в Base::foo есть параметр, заданный по-умолчанию,
поэтому этот вызов будет легальным,
если преобразовать его в pObj->bar(значение).
Вызов нужно построить уже сейчас.
А это значит, что нужно использовать раннее связывание для параметров.
Всё что у нас есть - указатель на Base.
Поэтому компилятор, основываясь на статическом типе,
считает, что работает с объектом типа Base и впихивает 42.
Теперь он может построить вызов pObj->bar(42).
Функция-член Base::bar виртуальная, это заставляет компилятор
использовать уже позднее связывание для вызова,
а это совершенно другая тактика построения кода.
Он может построить команды так:
1) взять в первых байтах объекта указатель на таблицу виртуальных функций,
2) пройти по адресу в указателе, и вызвать из этой таблицы функцию, соответствующую bar(int).
Псевдокод: ((vptr_t*)pObj))->bar_addr(42);
Таким образом и получаем, что связывание
виртуальных функций будет поздним, а их параметров - ранним.
Конечно, можно было организовать и позднее связывание параметров,
но для этого пришлось бы городить еще один огород с таблицами.
А так ли оно нужно? Да врядли оно настолько востребовано.
Просто нужно понимать что делаешь и тогда проблем не будет.

Добавлено через 7 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Интересно что Саша скажет.
Надеюсь, тебе стало чуть понятнее.
Извини, но объяснять - это не моё.
7
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
16.11.2016, 02:20
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
При этом компилятор всем
сердцем верит, что там объект типа Base*
Это сложный вопрос. Указатель содержит адрес объекта типа Base. Но можно использовать RTTI и выяснить действительный тип который находится по данному адресу.
А механизм v-table работает независимо от типа и в этом вторая половинка магии "динамической" типизации. Но вот, оказывается, что когда явно перегружен метод без аргумента, то v-table содержит их 2-штуки и у компилятора есть достаточно информации для вызова. А вот если используется аргумент по умолчанию, то различие аргументов нигде нельзя отметить, - нет для них места в v-table. И получается логический сбой! Это очень интересный момент. Жаль, что это компилируется, мне кажется.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.11.2016, 02:20
Помогаю со студенческими работами здесь

Формальные и фактические параметры в процедурах и функциях
Здравствуйте, я сейчас, наверное, задам один из глупых вопросов, но я никак не могу понять. У меня в скором времени экзамен по...

Как в JavaScript передаются параметры в функциях? По ссылке или по значению.
Как в JavaScript передаются параметры в функциях? По ссылке или по значению. И каков синтаксис в каждом из случаев. Сам ответ не...

Параметры функции: параметры по умолчанию
помогите пожалуйста понять. void foo(int a, int b, int c=1){std::cout &lt;&lt; a &lt;&lt; &quot;\t&quot; &lt;&lt; b &lt;&lt; &quot;\t&quot; &lt;&lt; c &lt;&lt; '\t';} int main(){ ...

Параметры по умолчанию в С.
Всем привет! Захотел воспользоватся параметрами по умолчанию в си-шном проекте. И получил следующие ошибки: Действительно данный...

Параметры по умолчанию в функции
Всем привет. Есть такой класс: template &lt;typename T&gt; class MyClass { public: MyClass(T *_beg, T *_en):beg(_beg),en(_en) {} ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru