Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.03.2018, 19:24   #1
cyberdev
Форумчанин
 
Аватар для cyberdev
 
Регистрация: 10.10.2013
Сообщений: 150
По умолчанию Точки останова в повторяющихся фрагментах кода

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

Код:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

  procedure Proc();
    var
      a, b, c : Integer;

    procedure Sub1();
    begin
      Dec(c, b);
      Inc(c);
    end;

    procedure Sub2();
    begin
      Dec(c, a);
    end;

  begin
    a := 1; b := 2; c := 3;
    Sub1();
    Writeln('c: ', c);
    Sub2();
    Writeln('c: ', c);
    Readln;
  end;


begin
  Proc();
end.
В C++ это можно сделать с помощью макросов

Код:
#include <iostream>

using namespace std;

int main()
{
    int a = 1, b = 2, c = 3;
    #define macro_1   \
            c -= b; \
            c++;
    #define macro_2 c -= a
    macro_1;
    cout << "c: " << c << endl;
    macro_2;
    cout << "c: " << c << endl;
    return 0;
}
Но если в Делфи можно поставить точку останова и наблюдать изменения во время отладки, то в C++ отладчик фрагменты в макросах просто не увидит. Как решить данную проблему в C++, чтобы отладчик видел эти фрагменты, как в Делфи?
Сайт о программировании и трехмерной графике - cybersite.ucoz.net
cyberdev вне форума Ответить с цитированием
Старый 13.03.2018, 20:53   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

1)макросы зло, есть шаблоны. + макросы совсем не тоже самое что локальные функции в Делфи.
2)используйте обычные функции, не локальные.(хотя можно через лямбды извратится...)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 13.03.2018, 22:02   #3
cyberdev
Форумчанин
 
Аватар для cyberdev
 
Регистрация: 10.10.2013
Сообщений: 150
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
1)макросы зло, есть шаблоны. + макросы совсем не тоже самое что локальные функции в Делфи.
Макрос просто копирует свой текст в указанное место, на сколько я помню. А то что, при этом доступ отладчика закрыт к этому тексту, это действительно зло.

Какие шаблоны?

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
2)используйте обычные функции, не локальные.(хотя можно через лямбды извратится...)
Не локальные функции не видят локальных переменных, а через параметры передавать их довольно муторно.

В результате, остаются только макросы, которые, к сожалению, не видит отладчик.
Сайт о программировании и трехмерной графике - cybersite.ucoz.net
cyberdev вне форума Ответить с цитированием
Старый 13.03.2018, 23:27   #4
Avazart
Форумчанин
 
Аватар для Avazart
 
Регистрация: 13.08.2011
Сообщений: 184
По умолчанию

Цитата:
Сообщение от cyberdev Посмотреть сообщение
локальные подпрограммы.
В С++ есть std::function и лямбды.

Цитата:
Сообщение от cyberdev Посмотреть сообщение
Какие шаблоны?
В С++ - шаблоны.
В Delphi - дженерики.

Цитата:
Сообщение от cyberdev Посмотреть сообщение
Не локальные функции не видят локальных переменных, а через параметры передавать их довольно муторно.
И это скорее всего - хорошо, чем плохо.
Avazart вне форума Ответить с цитированием
Старый 14.03.2018, 15:51   #5
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию

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

Передавай их в структурах/классах. ООП не зря придумали же.
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 14.03.2018, 18:44   #6
cyberdev
Форумчанин
 
Аватар для cyberdev
 
Регистрация: 10.10.2013
Сообщений: 150
По умолчанию

Цитата:
Сообщение от New man Посмотреть сообщение
Если тебе сложно передавать необходимые данные в виде аргументов, значит, код попахивает.
Что делает код? :-)

Цитата:
Сообщение от New man Посмотреть сообщение
Передавай их в структурах/классах. ООП не зря придумали же.
Засунуть все переменные в класс ради кусков кода, а потом обращаться к объекту ради получения доступа к обычной перемеренной... Я уже думал об этом, но в результате получится еще сложнее чем, передать переменные в функции через параметры. Но и этот вариант получится очень громоздким. На Делфи я давно бы уже всё написал. Не раз на нем делал подобное. Но нельзя, ЯП строго С++.

Цитата:
Сообщение от Avazart Посмотреть сообщение
В С++ - шаблоны
Мне не приходилось работать с шаблонами в С++. Ну вот, допустим, я объявил шаблон.

Код:
template <typename subprogram>
Как мне написать теперь локальную функцио для работы с локальными переменными и вызвать её.
Сайт о программировании и трехмерной графике - cybersite.ucoz.net
cyberdev вне форума Ответить с цитированием
Старый 14.03.2018, 18:52   #7
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Какой еще subprogram? Там имя типа (например T) для использования в этой функции или классе, вместо которого при вызове функции или создании экземпляра класса указывается настоящий тип (для функций бывает автоматически).

Например
Код:
std::vector<int> myNumbers;
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 14.03.2018, 19:19   #8
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию

Попахивает г*вном.

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

Функцию тоже можно рассматривать как модуль. В таком случае, то, что ты не можешь передать в модуль достаточное количество аргументов, говорит о том, что она у тебя сильно связана с остальным кодом.

Поясню тебе за интерфейсы.
Код:
int do_smthng(int argument)
{
   argument += 5;
   return argument;
}
В этом коде `int do_smthng(int argument)` — интерфейс. Это то, что вызывающему коду должно быть достаточно, чтобы обращаться к этой функции.
А вот это: реализация:
Код:
{
   argument += 5;
   return argument;
}
И интерфейс с реализацией должны быть разделены, то есть, изменение реализации не должно заставлять изменять интерфейс (и вызовы) везде. То есть, вызывающий код зависит только от интерфейса, что сильно всё упрощает.

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

Повторяю, твою проблему можно решить с помощью ООП.
Суть ООП в том, что объекты инкапсулируют в себе данные и методы их обработки.
То есть, тебе надо создать класс, который имеет следующий формат:
Код:
class SomeClass{
// данные, которые ты хочешь менять в виде полей
// методы класса, которые заменяют те локальные функции, изменяя данные в полях.
}
Далее в своей большой функции:
Код:
SomeClass my_data;
my_data.method1();
my_data.method2();
Это был первый способ.
Второй способ выноса локальных функций работает только для C++.
У тебя есть .h файл с описанием всех функций.
Ты можешь создать более одного cpp файла для него!
Хоть по одной на функцию.

И в cpp файле делаешь такой код:
Код:
struct Context{
 // Тут делаешь описания всех полей, которые тебе надо внутри большой функции
};

// локальные для cpp файла функции пишешь в таком формате
static int do_smth(Context& context, /*прочие аргументы*/)
{
// твой код
}

// Это та функция, которую ты описывал в h файле
void h_function(args)
{
   Context context; 
   // Тут инициализируешь поля
  // дальше можешь вызывать свои "локальные функции"
}
Тут важно слово "static" перед do_smth. Это слово означает, что функция существует только для этого cpp файла и не может быть вызвана снаружи.

Но этот метод достаточно плохой, плюс, он, по сути, является недоООП.

Ну, и последний, самый дрянной метод, который сломает мозги тому, кто будет поддерживать твой код, из-за чего этот псих найдёт тебя и зарубит топором.
Использование лямбда выражений!
Просто пишешь внутри метода:
Код:
  auto my_local_func = [&](int a, float b)
  {
       // Тут твой код
  };
  // ...
  my_local_func(6,8979.0);
По сути, это работает именно как локальные функции (пусть и с созданием объекта-функции).
Важная вещь — квадратные скобки.
[a, b, &c] — К обычным аргументам лямбда ещё примет копии a,b и ссылку на c, и сможет это использовать.
[=] — функция получит копию всего, что есть в верхней функции.
[&] — функция получит ссылку на все переменные, что есть в верхней. Это именно то, что в Delphi, python и т. п.

Надеюсь, я тебе прояснил твои возможности.
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 14.03.2018, 19:19   #9
cyberdev
Форумчанин
 
Аватар для cyberdev
 
Регистрация: 10.10.2013
Сообщений: 150
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Какой еще subprogram?
Я же говорю, никогда не работал с шаблонами в С++.

Работаю в данный момент со скриптовым языком, аналог С++. Лямбд там нет, std тоже. Работают только шаблоны. Но как их использовать в качестве локальных подпрограмм, понятия не имею и в интернете никакой информации по этому не нашел.

Цитата:
Сообщение от New man Посмотреть сообщение
Попахивает г*вном
Снова вы про него? Ну что за мода, делать такие выводы не зная цели для которой решается задача? Хватит! А то неприятно, аж сюда подванивает.
Сайт о программировании и трехмерной графике - cybersite.ucoz.net
cyberdev вне форума Ответить с цитированием
Старый 14.03.2018, 19:24   #10
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию

В таком случае у тебя остаётся только два варианта:
1) стиснуть зубы и отрефакторить код так, чтобы он нормально декомпозировался на меньшие функции;
2) писать как есть.

Цитата:
Сообщение от cyberdev Посмотреть сообщение
А то неприятно, аж сюда подванивает.
Конечно, это же Вы читаете свой код
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите найти ошибку: *.exe вызвал срабатывание точки останова Gretchem Waide Помощь студентам 2 04.11.2014 18:02
OllyDbg при срабатывани точки останова окно крэкми вызвать помогите пожалуста! Dimka-novitsek Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 13 11.04.2014 18:57
Debug, Отладка завершает программу после точки останова 3betmebabyImFamous Общие вопросы по Java, Java SE, Kotlin 0 09.08.2012 15:41
[РЕШЕНО] не работают точки останова VVkSoft Общие вопросы Delphi 9 31.10.2011 15:16
Точки останова Spot Общие вопросы Delphi 8 24.07.2010 19:56