Pages

Kamis, 22 November 2012

Materi Function C++ (Indonesian Version)


Fungsi
Argumen melewati nilai dan dengan referensi.

Sampai saat ini, di semua fungsi yang telah kita lihat, argumen dilewatkan ke fungsi telah melewati nilai. Ini berarti bahwa ketika memanggil fungsi dengan parameter, apa yang telah kita dilewatkan ke fungsi adalah salinan dari nilai-nilai mereka tapi tidak pernah variabel itu sendiri. Sebagai contoh, misalkan kita disebut fungsi pertama kami selain menggunakan kode berikut:

 int x=5, y=3, z;
 z = addition ( x , y );

Apa yang kita lakukan dalam hal ini adalah untuk memanggil berfungsi selain mengirimkan nilai x dan y, yaitu 5 dan 3 masing-masing, tetapi tidak variabel x dan y sendiri.




Dengan cara ini, ketika penambahan fungsi disebut, nilai dari variabel lokal dan b menjadi 5 dan 3 masing-masing, tetapi setiap modifikasi baik atau b dalam penambahan fungsi tidak akan memiliki efek apapun dalam nilai-nilai x dan y luar itu, karena variabel x dan y sendiri tidak dilewatkan ke fungsi, tetapi hanya salinan dari nilai-nilai mereka pada saat fungsi dipanggil.

Tapi mungkin ada beberapa kasus di mana Anda perlu untuk memanipulasi dari dalam fungsi nilai dari variabel eksternal. Untuk itu kita dapat menggunakan argumen dikirimkan dengan referensi, seperti dalam fungsi duplikat dari contoh berikut:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// passing parameters by reference
#include <iostream>
using namespace std;

void duplicate (int& a, int& b, int& c)
{
  a*=2;
  b*=2;
  c*=2;
}

int main ()
{
  int x=1, y=3, z=7;
  duplicate (x, y, z);
  cout << "x=" << x << ", y=" << y << ", z=" << z;
  return 0;
}
x=2, y=6, z=14



Hal pertama yang harus menarik perhatian Anda adalah bahwa dalam deklarasi menduplikasi jenis parameter masing-masing diikuti dengan tanda ampersand (&). Ampersand ini adalah apa yang menetapkan bahwa argumen yang berhubungan harus dilalui oleh referensi bukan oleh nilai.

Ketika sebuah variabel dilewatkan dengan referensi kita tidak melewati salinan nilainya, tapi kami entah bagaimana melewati variabel itu sendiri dengan fungsi dan modifikasi apapun yang kita lakukan untuk variabel lokal akan berpengaruh dalam variabel rekan mereka lulus sebagai argumen panggilan ke fungsi.




Untuk menjelaskan hal itu dengan cara lain, kita kaitkan a, b dan c dengan argumen berlalu pada panggilan fungsi (x, y, dan z) dan setiap perubahan yang kami lakukan pada dalam fungsi akan mempengaruhi nilai x di luar itu. Setiap perubahan yang kami lakukan pada b akan mempengaruhi y, dan sama dengan c dan z.

Itulah sebabnya output program kita, yang menunjukkan nilai-nilai yang tersimpan dalam x, y, dan z setelah panggilan untuk menduplikasi, menunjukkan nilai-nilai dari semua tiga variabel utama dua kali lipat.

Jika ketika mendeklarasikan fungsi berikut:

 
void duplicate (int& a, int& b, int& c)


kami telah menyatakan dengan cara ini:

 
void duplicate (int a, int b, int c)


yaitu, tanpa tanda-tanda ampersand (&), kita akan tidak lulus variabel dengan referensi, namun salinan dari nilai-nilai mereka bukan, dan karena itu, output pada layar program kami akan menjadi nilai x, y, dan z tanpa yang telah dimodifikasi.

Lewat referensi juga merupakan cara yang efektif untuk memungkinkan fungsi untuk mengembalikan lebih dari satu nilai. Sebagai contoh, di sini adalah fungsi yang mengembalikan angka sebelumnya dan berikutnya dari parameter pertama berlalu.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// more than one returning value
#include <iostream>
using namespace std;

void prevnext (int x, int& prev, int& next)
{
  prev = x-1;
  next = x+1;
}

int main ()
{
  int x=100, y, z;
  prevnext (x, y, z);
  cout << "Previous=" << y << ", Next=" << z;
  return 0;
}
Previous=99, Next=101  


Standar nilai dalam parameter.
Ketika mendeklarasikan fungsi kita dapat menentukan nilai default untuk masing-masing parameter terakhir. Nilai ini akan digunakan jika argumen yang sesuai dibiarkan kosong saat memanggil ke fungsi. Untuk melakukan itu, kita hanya harus menggunakan operator penugasan dan nilai argumen dalam deklarasi fungsi. Jika nilai parameter yang tidak lulus saat fungsi ini dipanggil, nilai default digunakan, tetapi jika nilai tersebut ditentukan nilai default ini diabaikan dan nilai berlalu digunakan sebagai gantinya. Sebagai contoh:


// default values in functions
#include <iostream>
using namespace std;

int divide (int a, int b=2)
{
  int r;
  r=a/b;
  return (r);
}

int main ()
{
  cout << divide (12);
  cout << endl;
  cout << divide (20,4);
  return 0;
}


Seperti yang bisa kita lihat dalam tubuh program ada dua panggilan berfungsi membagi. Dalam yang pertama:

 
divide (12)


kita hanya ditentukan satu argumen, tapi membagi fungsi memungkinkan hingga dua. Jadi membagi fungsi telah diasumsikan bahwa parameter kedua adalah 2 karena itu adalah apa yang kita telah ditentukan untuk terjadi jika parameter ini tidak lulus (perhatikan deklarasi fungsi, yang berakhir dengan int = 2 b b, tidak hanya int). Oleh karena itu hasil dari pemanggilan fungsi ini adalah 6 (12/2).

Pada panggilan kedua:

 
divide (20,4)


ada dua parameter, sehingga nilai default untuk b (int b = 2) diabaikan dan b mengambil nilai yang dikirimkan sebagai argumen, yaitu 4, membuat hasilnya dikembalikan sebesar 5 (20/4).

Kelebihan beban fungsi.
Dalam C + + dua fungsi yang berbeda dapat memiliki nama yang sama jika parameter mereka jenis atau nomor berbeda. Itu berarti bahwa Anda dapat memberikan nama yang sama untuk lebih dari satu fungsi jika mereka memiliki sebuah nomor yang berbeda dari parameter atau jenis yang berbeda dalam parameter mereka. Sebagai contoh:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// overloaded function
#include <iostream>
using namespace std;

int operate (int a, int b)
{
  return (a*b);
}

float operate (float a, float b)
{
  return (a/b);
}

int main ()
{
  int x=5,y=2;
  float n=5.0,m=2.0;
  cout << operate (x,y);
  cout << "\n";
  cout << operate (n,m);
  cout << "\n";
  return 0;
}
10
2.5


Dalam kasus ini kita telah mendefinisikan dua fungsi dengan nama yang sama, beroperasi, tapi salah satu dari mereka menerima dua parameter bertipe int dan yang lainnya menerima mereka tipe float. Compiler tahu mana yang untuk memanggil setiap kasus dengan memeriksa jenis lulus sebagai argumen saat fungsi ini dipanggil. Jika disebut dengan dua ints sebagai argumen itu panggilan ke fungsi yang memiliki dua parameter int dalam prototipe dan jika hal itu disebut dengan dua mengapung ia akan menelepon ke salah satu yang memiliki dua parameter mengapung di prototipe.

Pada panggilan pertama untuk mengoperasikan dua argumen berlalu adalah dari tipe int, oleh karena itu, fungsi dengan prototipe pertama disebut, fungsi ini mengembalikan hasil perkalian dua parameter. Sedangkan panggilan kedua melewati dua argumen tipe float, sehingga fungsi dengan prototipe kedua disebut. Yang satu ini memiliki perilaku yang berbeda: ia membagi satu parameter oleh yang lain. Jadi perilaku panggilan untuk beroperasi tergantung pada jenis argumen berlalu karena fungsi telah kelebihan beban.

Perhatikan bahwa fungsi tidak dapat kelebihan beban hanya dengan jenis kembalinya. Setidaknya salah satu parameter yang harus memiliki tipe yang berbeda.

fungsi inline.
Specifier inline menunjukkan bahwa substitusi compiler inline lebih disukai untuk mekanisme pemanggilan fungsi biasa untuk fungsi tertentu. Hal ini tidak mengubah perilaku fungsi itu sendiri, tetapi digunakan untuk menunjukkan kepada compiler bahwa kode yang dihasilkan oleh fungsi tubuh dimasukkan pada setiap titik fungsi ini dipanggil, bukannya dimasukkan hanya sekali dan melakukan panggilan biasa untuk itu , yang umumnya melibatkan beberapa overhead tambahan dalam waktu berjalan.

Format untuk deklarasi adalah:

jenis inline Nama (argumen ...) {petunjuk ... }

dan panggilan seperti panggilan ke fungsi lainnya. Anda tidak perlu memasukkan kata kunci inline saat memanggil fungsi, hanya dalam deklarasi.

Sebagian besar kompiler sudah mengoptimalkan kode untuk menghasilkan fungsi inline ketika itu lebih nyaman. Ini specifier hanya menunjukkan bahwa compiler inline lebih disukai untuk fungsi ini.

Recursivity.
Recursivity adalah properti yang berfungsi harus dipanggil sendiri. Hal ini berguna untuk banyak tugas, seperti pemilahan atau menghitung faktorial dari angka. Misalnya, untuk mendapatkan faktorial dari sejumlah (n!) rumus matematika akan menjadi:

 n!  = N * (n-1) * (n-2) * (n-3) ...  * 1


lebih konkret, 5! (Faktorial 5) akan menjadi:

 5!  = 5 * 4 * 3 * 2 * 1 = 120


dan fungsi rekursif untuk menghitung ini dalam C + + dapat:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// factorial calculator
#include <iostream>
using namespace std;

long factorial (long a)
{
  if (a > 1)
   return (a * factorial (a-1));
  else
   return (1);
}

int main ()
{
  long number;
  cout << "Please type a number: ";
  cin >> number;
  cout << number << "! = " << factorial (number);
  return 0;
}
Please type a number: 9
9! = 362880  



Perhatikan bagaimana dalam fungsi faktorial kami termasuk panggilan untuk dirinya sendiri, tetapi hanya jika argumen berlalu lebih besar dari 1, karena jika fungsi akan melakukan loop rekursif tak terbatas di mana setelah tiba ke 0 akan terus mengalikan oleh semua angka negatif ( mungkin memprovokasi kesalahan stack overflow pada runtime).

Fungsi ini memiliki keterbatasan karena jenis data yang kita digunakan dalam desain (panjang) untuk kesederhanaan lebih. Hasil yang diberikan tidak akan berlaku untuk nilai-nilai yang jauh lebih besar dari 10! atau 15!, tergantung pada sistem Anda compile.

Mendeklarasikan fungsi.
Sampai saat ini, kita telah mendefinisikan semua fungsi sebelum penampilan pertama dari panggilan kepada mereka dalam kode sumber. Panggilan ini umumnya dalam fungsi utama yang kami selalu meninggalkan pada akhir kode sumber. Jika Anda mencoba untuk mengulangi beberapa contoh fungsi yang dijelaskan sejauh ini, tapi menempatkan fungsi utama sebelum salah satu fungsi lain yang disebut dari dalamnya, Anda kemungkinan besar akan mendapatkan kompilasi kesalahan. Alasannya adalah bahwa untuk dapat memanggil fungsi itu harus telah dinyatakan di beberapa titik sebelumnya dari kode, seperti yang telah kita lakukan di semua contoh kami.

Tapi ada cara alternatif untuk menghindari menulis kode seluruh fungsi sebelum dapat digunakan dalam utama atau dalam beberapa fungsi lainnya. Hal ini dapat dicapai dengan menyatakan hanya prototipe fungsi sebelum digunakan, bukan seluruh definisi. Deklarasi ini lebih pendek dari seluruh definisi, namun cukup signifikan untuk compiler untuk menentukan jenis kembali dan jenis parameter.

Bentuknya adalah:

ketik nama (argument_type1, argument_type2, ...);

Hal ini identik dengan definisi fungsi, kecuali bahwa ia tidak termasuk tubuh fungsi itu sendiri (yaitu, pernyataan fungsi bahwa dalam definisi normal diapit oleh kurung {}) dan bukannya kita mengakhiri deklarasi prototipe dengan titik koma wajib (;).

Pencacahan Parameter tidak perlu menyertakan pengenal, tetapi hanya penspesifikasi jenis. Dimasukkannya nama untuk setiap parameter seperti dalam definisi fungsi adalah opsional dalam deklarasi prototipe. Sebagai contoh, kita dapat mendeklarasikan fungsi yang disebut protofunction dengan dua parameter int dengan salah satu deklarasi berikut:


1
2
int protofunction (int first, int second);
int protofunction (int, int);


Pokoknya, termasuk nama untuk masing-masing variabel membuat prototipe lebih mudah dibaca.


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
// declaring functions prototypes
#include <iostream>
using namespace std;

void odd (int a);
void even (int a);

int main ()
{
  int i;
  do {
    cout << "Type a number (0 to exit): ";
    cin >> i;
    odd (i);
  } while (i!=0);
  return 0;
}

void odd (int a)
{
  if ((a%2)!=0) cout << "Number is odd.\n";
  else even (a);
}

void even (int a)
{
  if ((a%2)==0) cout << "Number is even.\n";
  else odd (a);
}
Type a number (0 to exit): 9
Number is odd.
Type a number (0 to exit): 6
Number is even.
Type a number (0 to exit): 1030
Number is even.
Type a number (0 to exit): 0
Number is even.



Contoh ini memang bukan contoh efisiensi. Saya yakin bahwa pada titik ini Anda sudah bisa membuat program dengan hasil yang sama, tetapi menggunakan hanya setengah dari baris kode yang telah digunakan dalam contoh ini. Pokoknya contoh ini menggambarkan bagaimana prototyping bekerja. Selain itu, dalam contoh beton prototipe dari setidaknya satu dari dua fungsi yang diperlukan dalam rangka untuk mengkompilasi kode tanpa kesalahan.

Hal pertama yang kita lihat adalah deklarasi fungsi ganjil dan genap:


1
2
void odd (int a);
void even (int a); 


Hal ini memungkinkan fungsi-fungsi yang akan digunakan sebelum mereka didefinisikan, misalnya, di utama, yang sekarang terletak di mana beberapa orang merasa menjadi tempat yang lebih logis untuk memulai sebuah program: awal dari kode sumber.

Pokoknya, alasan mengapa program ini membutuhkan setidaknya salah satu fungsi yang harus dideklarasikan sebelum didefinisikan karena dalam aneh ada panggilan untuk bahkan dan bahkan ada panggilan untuk aneh. Jika tidak ada dua fungsi sebelumnya telah menyatakan, kesalahan kompilasi akan terjadi, karena baik aneh tidak akan terlihat dari bahkan (karena masih belum dinyatakan), atau bahkan tidak akan terlihat dari aneh (untuk alasan yang sama) .

Memiliki prototipe dari semua fungsi bersama-sama di tempat yang sama dalam kode sumber ditemukan praktis oleh beberapa programmer, dan ini dapat dengan mudah dicapai dengan menyatakan semua prototipe fungsi pada awal program.

0 komentar:

Posting Komentar