Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

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

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

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

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

Код:

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, 21:53   #2
Пепел Феникса
Модератор
Заслуженный модератор
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Адрес: Москва
Сообщений: 21,006
Репутация: 3402

icq: 446843180
skype: phoenix_proger
По умолчанию

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

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

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

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

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

Цитата:
Сообщение от cyberdev Посмотреть сообщение
локальные подпрограммы.
В С++ есть std::function и лямбды.
Avazart вне форума   Ответить с цитированием
Старый 14.03.2018, 00:28   #5
Avazart
Форумчанин
 
Аватар для Avazart
 
Регистрация: 13.08.2011
Сообщений: 146
Репутация: 211
По умолчанию

Цитата:
Сообщение от cyberdev Посмотреть сообщение
Какие шаблоны?
В С++ - шаблоны.
В Delphi - дженерики.
Avazart вне форума   Ответить с цитированием
Старый 14.03.2018, 00:30   #6
Avazart
Форумчанин
 
Аватар для Avazart
 
Регистрация: 13.08.2011
Сообщений: 146
Репутация: 211
По умолчанию

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

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

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

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

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

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

Код:

template <typename subprogram>

Как мне написать теперь локальную функцио для работы с локальными переменными и вызвать её.
__________________
Сайт о программировании и трехмерной графике - cybersite.ucoz.net
cyberdev вне форума   Ответить с цитированием
Старый 14.03.2018, 19:52   #9
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 16,147
Репутация: 3199

icq: 512-765
skype: alexp.frl
По умолчанию

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

Например
Код:

std::vector<int> myNumbers;

Alex11223 на форуме   Ответить с цитированием
Старый 14.03.2018, 20:19   #10
New man
Участник клуба
 
Регистрация: 24.01.2011
Сообщений: 685
Репутация: 241
По умолчанию

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

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

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

Поясню тебе за интерфейсы.
Код:

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 вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите найти ошибку: *.exe вызвал срабатывание точки останова Gretchem Waide Помощь студентам 2 04.11.2014 19:02
OllyDbg при срабатывани точки останова окно крэкми вызвать помогите пожалуста! Dimka-novitsek Assembler 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


22:45.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru