Многократное повторение одинаковых фрагментов кода внутри функции - страница 2

 
Mihail Matkovskij:
Возможно, у кого-то возникала такая проблема, когда один и от же фрагмент кода нужно копировать много раз в различные места функции. Но если одинаковых фрагментов становится слишком много, то становится очень сложно за ними уследить. Делаем изменение в одном фрагменте и тут же, надо искать все идентичные фрагменты и делать там это же изменение много раз. Конечно, можно воспользоваться автозаменой текста. Но всё же, есть способ на много эффективнее, заключить повторяющийся фрагмент в функцию и всталять её сколько угодно раз, там где это необходимо. Но проблема кроется здесь вот в чём. Во первых, вызываемая функция не видит локальных переменных вызывающей её функции. Во вторых, указатели на объекты в параметрах работают только для чтения, но не для записи (следовательно, нельзя передать объекты из вызываемой функцию посредством параметров). По данной проблеме у меня даже есть тема с примером: https://www.mql5.com/ru/forum/227475 . Таким образом, если локальные переменные передать через параметры по адресу, то объекты передать не получится. Кто как выходит из подобных ситуаций, с многократным повторением одних и тех же фрагментов кода?

Почему нельзя объект в функцию передать?

class CObject
{
private:
   string Name;
public:
   string SetName(string name) {Name=name;};

}

void Func(CObject &Obj)
{
    Obj.SetName("Name");
}
 
Комбинатор:

Начните с наглядного примера проблемы, если тема не для просто поболтать

void func_1(){
  int a = 1, b = 2, c = 3;
  class CLocalFunc{
    public:
      void lc_f_1(){
        c -= b;
      }
      void lc_f_2(){
        c -= a;
      }
  };
  
  CLocalFunc Local;
  Local.lc_f_1();
  Local.lc_f_2();
}

Вот Вам простой пример для наглядности. Действия с a, b и c, в функциях lc_f_1 и lc_f_2 - многократно повторяющийся код, который может вызываться очень много раз.

 
Vitalii Ananev:

Почему нельзя объект в функцию передать?

Так Name, это уже поле класса. Это даже не глобальная переменная в модуле. Таким образом, придется изрядно переделать весь код, чего мне бы не хотелось. Мне нужно оптимальное решение.
 
Mihail Matkovskij:
Возможно, у кого-то возникала такая проблема, когда один и от же фрагмент кода нужно копировать много раз в различные места функции. Но если одинаковых фрагментов становится слишком много, то становится очень сложно за ними уследить. Делаем изменение в одном фрагменте и тут же, надо искать все идентичные фрагменты и делать там это же изменение много раз. Конечно, можно воспользоваться автозаменой текста. Но всё же, есть способ на много эффективнее, заключить повторяющийся фрагмент в функцию и всталять её сколько угодно раз, там где это необходимо. Но проблема кроется здесь вот в чём. Во первых, вызываемая функция не видит локальных переменных вызывающей её функции. Во вторых, указатели на объекты в параметрах работают только для чтения, но не для записи (следовательно, нельзя передать объекты из вызываемой функцию посредством параметров). По данной проблеме у меня даже есть тема с примером: https://www.mql5.com/ru/forum/227475 . Таким образом, если локальные переменные передать через параметры по адресу, то объекты передать не получится. Кто как выходит из подобных ситуаций, с многократным повторением одних и тех же фрагментов кода?

Кусок написать в отдельном файле, скажем kusok.h.

И когда надо кудато вставить просто пишим  #include "kusok.h"   Вот и все ;)

 
Mihail Matkovskij:

Вот Вам простой пример для наглядности. Действия с a, b и c, в функциях lc_f_1 и lc_f_2 - многократно повторяющийся код, который может вызываться очень много раз.

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

Ваш код отлично преобразуется к виду

void func_1(){}
 

Выделены следующие проблемы функций для повторяющегося участка кода:

1. Не видно локальных переменных.

2. Указатели только для чтения.

Я вижу следующие решения.

1. Если нужно видеть до пяти локальных переменных - проще всего вывести их в параметры функции. Если нужно видеть больше локальных переменных - то, на мой взгляд, это не самый лучший подход к алгоритму вобще. Большое число переменных разумно группировать в массивы и/или структуры. Соответственно, в повторяющийся участок, оформленный в виде функции передаются указатели на структуру.

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


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

 
Alexander Belkin:

Кусок написать в отдельном файле, скажем kusok.h.

И когда надо кудато вставить просто пишим  #include "kusok.h"   Вот и все ;)

Это будет не очень удобно, доя каждого куска кода отдельный файл. И глазное, будет ли видеть этот файл локальные переменные функции? Не охота проверять.
 
Mihail Matkovskij:
Это будет не очень удобно, доя каждого куска кода отдельный файл. И глазное, будет ли видеть этот файл локальные переменные функции? Не охота проверять.

#include  КОПИРУЕТ содержимое файла как текст))) Это равносильно тому что вы скопируете текст из файла который описан в #include  непосредственно в код.


Соответственно если кусок кода скопировать (что одно и тоже что описать его в #include) конечно код который в файле будет видеть и локальные и глобальные переменные точно также как его бы видел тотже кусок кода который был бы на месте #include "kusok.h"

 

@Mihail Matkovskij  так если у вас один и тотже кусок кода)))  всего один файл и нужен.

А в том месте где хотите ВСТАВИТЬ СОДЕРЖИМОЕ кода который описан в файле kusok.h пишите в коде советника/индикатора/скрипта #include "kusok.h" 

 

Поскольку, класс не увидел локальных переменных в моём предыдущем примере, то остается запихнуть их туда. Другого варианта не вижу. Остальные варианты кажутся мне сложно реализуемыми. А так можно получить аналог локальных подпрограмм в Делфи:

void func_1(){
  class CLocalFunc{
    public:
      int a, b, c;
      CLocalFunc(){
        a = 1; 
        b = 2; 
        c = 3;
      }
      void lc_f_1(){
        c -= b;
      }
      void lc_f_2(){
        c -= a;
      }
  };
  
  CLocalFunc Local;
  Local.lc_f_1();
  Local.lc_f_2();
  Print("Local.c: ", Local.c);
}

Возможно, кому нибудь данный пример пригодится.