5. Funkcje własne.

5.6. Przekazywanie danych: kopiowanie

W poprzednim rozdziale zostały opisane 2 sposoby przekazywania danych do funkcji własnej: poprzez kopiowanie oraz z wykorzystaniem wskaźników. W tym rozdziale pokażę, że podczas kopiowania danych do funkcji własnej pracuje ona z ich kopiami i nie jest w stanie zamienić oryginalnych wartości. W tym celu posłużymy się kodem 2 z rozdziału 5.2, do którego dodamy kilka funkcji Print() (kod 1). W poniższym kodzie funkcja CylinderVolume() nie dokonuje obliczeń, a po prostu zwraca 0.0.

Kod 1
#property strict

void OnStart()
  {
   double r = 1.0;
   double h = 2.5;

   //--- wyświetlenie zmiennych PRZED wywołaniem funkcji
   Print("1) Przed wywołaniem funkcji własnej: r = ", DoubleToString(r, 1),
         ", h = ", DoubleToString(h, 1));

   //--- wywołanie funkcji własnej
   double v = CylinderVolume(r, h);

   //--- wyświetlenie zmiennych PO wywołaniu funkcji
   Print("4) Po wywołaniu funkcji własnej: r = ", DoubleToString(r, 1),
         ", h = ", DoubleToString(h, 1));
  }

//--- opis funkcji własnej CylinderVolume()
double CylinderVolume(double radius, double height) // kopiowanie wartości
  {
   //--- wyświetlenie parametrów wewnątrz funkcji PRZED ich zmianą
   Print("2) Wewnątrz funkcji własnej przed zmianą: radius = ", DoubleToString(radius, 1),
          ", height = ", DoubleToString(height, 1));

   //--- zmiana wartości parametrów
   radius = radius + 5.0;
   height = height - 2.2;

   //--- wyświetlenie parametrów wewnątrz funkcji PO ich zmianie
   Print("3) Wewnątrz funkcji własnej po zmianie: radius = ", DoubleToString(radius, 1),
         ", height = ", DoubleToString(height, 1));

   return(0.0);
  }

Zobaczmy co pokaże ten skrypt w logach dziennika terminala MetaTrader 4 (rys. 1).

Rys. 1. Wynik działania skryptu.


W kodzie skryptu zaraz po utworzeniu zmiennych r i h za pomocą Print() wyświetlimy ich wartości (kod 2), co widać na rys. 1: "Test EURUSD,H1: 1) Przed wywołaniem funkcji własnej: r = 1.0, h = 2.5".

Kod 2
#property strict

void OnStart()
  {
   double r = 1.0;
   double h = 2.5;

   //--- wyświetlenie zmiennych PRZED wywołaniem funkcji
   Print("1) Przed wywołaniem funkcji własnej: r = ", DoubleToString(r, 1),
         ", h = ", DoubleToString(h, 1));
   //...
  }
//...

Następnie idzie wywołanie funkcji CylinderVolume(), do której przekazujemy te dwie zmienne. Sterowanie przechodzi do tej funkcji, gdzie od razu wyświetlimy początkowe wartości parametrów radius i height (kod 3). W dzienniku logów widzimy wpis: "Test EURUSD,H1: 2) Wewnątrz funkcji własnej przed zmianą: radius = 1.0, height = 2.5" (rys. 1). Widzimy, że są one równe argumentom r i h.

Kod 3
#property strict

void OnStart()
  {
   //...
   //--- wywołanie funkcji własnej
   double v = CylinderVolume(r, h);
   //...
  }

//--- opis funkcji własnej CylinderVolume()
double CylinderVolume(double radius, double height) // kopiowanie wartości
  {
   //--- wyświetlenie parametrów wewnątrz funkcji PRZED ich zmianą
   Print("2) Wewnątrz funkcji własnej przed zmianą: radius = ", DoubleToString(radius, 1),
          ", height = ", DoubleToString(height, 1));
   //...
  }

Teraz zmieniamy wartości parametrów (kod 4). Do radius dodajemy 5.0 (radius = 1.0 + 5.0 = 6.0), a od height odejmujemy 2.2 (height = 2.5 - 2.2 = 0.3). Te nowe wartości zobaczymy w logach terminala: "Test EURUSD,H1: 3) Wewnątrz funkcji własnej po zmianie: radius = 6.0, height = 0.3" (rys. 1).

Kod 4
#property strict

void OnStart()
  {
   //...
  }

//--- opis funkcji własnej CylinderVolume()
double CylinderVolume(double radius, double height) // kopiowanie wartości
  {
   //...
   //--- zmiana wartości parametrów
   radius = radius + 5.0;
   height = height - 2.2;

   //--- wyświetlenie parametrów wewnątrz funkcji PO ich zmianie
   Print("3) Wewnątrz funkcji własnej po zmianie: radius = ", DoubleToString(radius, 1),
         ", height = ", DoubleToString(height, 1));
   //...
  }

A teraz gwóźdź programu. Czy oryginalne wartości zmiennych r i h też się zmienią czy nie? Wiemy, że funkcja własna CylinderVolume() pracowała z ich kopiami, dlatego po wywołaniu funkcji pozostaną one takie same jak i przed jej wywołaniem (kod 5). Potwierdzenie tego faktu znajdziemy w logach: "Test EURUSD,H1: 4) Po wywołaniu funkcji własnej: r = 1.0, h = 2.5" (rys. 1).

Kod 5
#property strict

void OnStart()
  {
   //...
   //--- wyświetlenie zmiennych PO wywołaniu funkcji
   Print("4) Po wywołaniu funkcji własnej: r = ", DoubleToString(r, 1),
         ", h = ", DoubleToString(h, 1));
  }
//...

W następnym rozdziale pokażę jak działają wskaźniki.