Mustafa Kemal Üniversitesi Bilgisayar Mühendisliği Bölümü Ders Materyal Ve Notları

Sponsor

14 Temmuz 2014 Pazartesi

C++’ın Template Sihirbazı

Posted by samgar at 12:29 0 Comments


Nesne yönelimli programlama ilgilenmiş olanların ilk öğrendiği kalıplardan biri overloaded(aşırı yüklenmiş) fonksiyon tipleridir. Aşırı yüklenmiş fonksiyonlar Farklı tipte parametreler alan veya farklı tipte değer döndüren aynı isimli fonksiyonlardır. Generic ile aşırı yüklenmiş fonksiyonlar arasındaki temel fark aşırı yüklenmiş fonksiyonlar da her fonksiyon için ayrı kod yazılır ve her fonksiyon başka başka işlemler yapabilir. Generic fonksiyonlar farklı tipte değerlerin alınıp aynı işlemlerinin yapılması gereken durumlarda kullanılır.
Nesne yönelimdeki template nin tam Türkçesini bilmediğim için yazımda kullanamıyorum. Eğer öğrenirsem metini düzeltebilirim. Kodları linux altında derledim.Yeni bir Linux kullanıcısı olarak programlam geliştirmek için en iyi ortamın Linux olduğunu düşünüyorum eğer bu metinle ilgileniyorsanız ve Linux kullanmıyorsanız bir an once geçmenizi tavsiye ederim dedikten sonra…

Generic Fonsiyonlar:
Nesne yönelimli programlama ilgilenmiş olanların ilk öğrendiği kalıplardan biri overloaded(aşırı yüklenmiş) fonksiyon tipleridir. Aşırı yüklenmiş fonksiyonlar Farklı tipte parametreler alan veya farklı tipte değer döndüren aynı isimli fonksiyonlardır. Generic ile aşırı yüklenmiş fonksiyonlar arasındaki temel fark aşırı yüklenmiş fonksiyonlar da her fonksiyon için ayrı kod yazılır ve her fonksiyon başka başka işlemler yapabilir. Generic fonksiyonlar farklı tipte değerlerin alınıp aynı işlemlerinin yapılması gereken durumlarda kullanılır.
Generic Fonksiyonların temel kullanılışı şöyledir.
template <class tip> dönüş_Tipi fonksyionismi(parametre_Listesi)
Aklınıza nerelerde kullanılır bu generic sorusu gelebilir hemen cevaplayayım. Örneğin aldığı parametreleri hangi tipte gelirse gelsin ekrana yazdıran bir fonksiyon yazmak isteyebilirsiniz. Eğer aşırı yüklenmiş fonksiyonlar kullanmak isterseniz her tip parametre için bir fonksiyon yazmanız gerekir (int, char, double). Yazının sonunda generic fonksiyonların kullanım alanları hakkında biraz bilgi vermeye çalışacağım(unutabilirim de) önce inceleyelim. Hemen başlayalım…
#include <iostream>
using namespace std;
template <class MYCLS>void yazdir (MYCLS deg1,MYCLS deg2){


cout<<"deg1 Değeri:"<<deg1<<"\n";
cout<<"deg2 Değeri:"<<deg2<<"\n";

cout<<"\n";
};
int main(){

//Fonksiyonumuza Parametre olarak Katar Gönderiyouz
yazdir("Merhaba","Dünya");

//int tipinde parametre göndersek bile çalışıyor
yazdir(10,20);

//double veya float tipindeki değişkenler içinde sorunsuz çalışıyor
yazdir(10.20,123.123);

};
—————————————————
deg1 Değeri:Merhaba
deg2 Değeri:Dünya
deg1 Değeri:10
deg2 Değeri:20
deg1 Değeri:10.2
deg2 Değeri:123.123
—————————————————
Yukarıdaki yazdığımız kodu elbette aşırı yüklenmiş fonksiyonlarla yapabilirdik ama chr için ayrı, int için ayrı, float için ayrı fonksiyon yazmamız gerekirdi. En az kod kullanarak çok esnek bi kod yazmış olduk demekki doğru yoldayız devam edelim.
Daha anlaşılır olması için başka bir örenek daha vereyim. Aldığı 2 parametreyi birbirine aktaran bir kod yazalım… Aşşağıdaki fonksiyonda referans kullanılmıştır referansları bildiğini varsayarak devam ediyorum…
#include <iostream>
using namespace std;
template <class MYCLS>void degistir (MYCLS &deg1,MYCLS &deg2){
MYCLS gecici;

cout<<"Gelen değer Deg1:"<<deg1<<"\n";
cout<<"Gelen değer Deg2:"<<deg2<<"\n";

gecici=deg1;
deg1=deg2;
deg2=gecici;
}
int main(){
int int1,int2;
char char1,char2;
float float1,float2;

int1=10;
int2=20;
degistir(int1,int2);
cout<<"Dönen değer int1:"<<int1<<"\n";
cout<<"Dönen değer int2:"<<int2<<"\n\n";

char1=’A';
char2=’B';

degistir(char1,char2);
cout<<"Dönen değer char1:"<<char1<<"\n";
cout<<"Dönen değer char2:"<<char2<<"\n\n";

float1=10.01;
float2=20.02;
degistir(float1,float2);
cout<<"Dönen değer float1:"<<float1<<"\n";
cout<<"Dönen değer float2:"<<float2<<"\n\n";

}
——————————————-
Gelen değer Deg1:10
Gelen değer Deg2:20
Dönen değer int1:20
Dönen değer int2:10
Gelen değer Deg1:A
Gelen değer Deg2:B
Dönen değer char1:B
Dönen değer char2:A
Gelen değer Deg1:10.01
Gelen değer Deg2:20.02
Dönen değer float1:20.02
Dönen değer float2:10.01
——————————————-
İçerde neler olduğunu merak ediyorsunuzdur. Biz generic fonksiyon tanımladığımızda derleyici hemen bizim yerimize gelebilecek bütün tipler için fonksiyonlar tanımlar biz gerisiyle ilgilenmeyiz.
Yukarıdaki fonksiyonumuzda aynı tipteki iki parametre üzerinde işlemler yaptık peki iki farklı tiptlerde parametre alamazmı bu generic fonksiyonlar mesele birini int birini char olarak? Elbette alır hemen kücük bir örenkele devam edelim…
#include <iostream>
using namespace std;
template <class MYCLS1, class MYCLS2>
void yazdir(MYCLS1 deg1, MYCLS2 deg2){
cout << deg1 << ‘ ‘ << deg2 << ‘\n’;
}
int main(){
yazdir("2×5=",10);
yazdir(10,19.99);
yazdir(10,"Yıl önce");
}
—————————–
2×5= 10
10 19.99
10 Yıl önce
—————————–
Peki değişken tipte parametreler tanımladık biz bunların yerine sabit tipte parametreler tanımlayamazmıyız. Tabi ki buda düşünülmüş kücük bir örnek de ona verelim ordan da aşırı yüklenmiş generic fonksiyonlara geçeriz.
#include <iostream>
using namespace std;
template <class MYCLS> void yazdir(MYCLS deg1, int deg2){
cout<<"MYCLS deg1="<<deg1<<"\n";
cout<<"int deg2 ="<<deg2<<"\n";
}
int main(){
yazdir("2×5",10);
yazdir(10,10);
yazdir(10.50,10);
}
———————-
MYCLS deg1=2×5
int deg2 =10
MYCLS deg1=10
int deg2 =10
MYCLS deg1=10.5
int deg2 =10
———————-
Yukarıdaki örnek üzerinde fazla durmadan geçmek istiyorum zaten basit bir kod. sıradaki konumuz aşırı yüklenmiş generic fonksiyonlar.
Generic fonksiyonlar iki şekilde aşırı yüklenirler. Birincisi bir generic fonksiyon basit bir fonksiyon ile aşırı yüklenir, ikincisi bir generic fonksiyon başka bir generic fonksiyon ile aşırı yüklenir. Önce birinci tipdeki aşırı yükleme üzerinde duralım.

#include <iostream>
using namespace std;
template <class MYCLS> void yazdir(MYCLS deger){
cout <<"Gelen Deger ="<<deger<<"\n";
};
void yazdir(int intdeger){
cout<<"\nBurası Basit Fonkisyonumuzun Bloğu\n";
cout<<"Gelen intDeger="<<intdeger<<"\n";
}
int main(){

yazdir("Merhaba Dünya");
yazdir(19);
}
———————————–
Gelen Deger =Merhaba Dünya
Burası Basit Fonkisyonumuzun Bloğu
Gelen intDeger=19
———————————–
Çıktıya dikkat edin. İlk yazdir() çağrımızda generic fonksiyon çalışırken ikinci çağrıda basit fonksyionumuz çağrılıyor. Çünkü derleyicimize “void yazdir(int intdeger){}” tanımı ile sadece int tipinde bir değer gelirse bu çağrıyı basit fonksiyon ile yapması için talimat veriyoruz. Benzer şekilde katarlar ve float içinde aynı tanımlamayı yapmamız mümkün. Böyle bir tanımlama yaptığımızda sadece int tipinde gelen parametreler için basit fonksiyon kullanılır diğer bütün tipteki parametreler için generic fonksiyonumuz görevi devralacaktır. Generic fonksiyon içinde tanımladığımız rutin çağrılarının dışına çıkmak istediğimizde kullanabileceğimiz bir metod. Örneğin anlaşılır olduğunu düşünüp generic fonlksiyonu generic fonksiyon ile aşırı yükleme yi anlatmak istedim.
İkinci tipteki aşırı yüklenmiş fonksiyon bilinen aşırı yüklenmiş fonksiyon biçiminde çalışır. Farklı sayıda değişken alan rutin işlemler yapan fonksiyonlar için bu tanımlama yapılabilir. kodumuz aşşağıda inceleyelim…
#include <iostream>
using namespace std;
template <class MYCLS> void yazdir(MYCLS deger){
cout<<"\nBurası tek parametre alıyorsa çalışır\n";
cout <<"Gelen Deger ="<<deger<<"\n";
};
template <class MYCLS> void yazdir(MYCLS deg1,MYCLS deg2){
cout<<"\nBurası iki parametre alıyorsa çalışır\n";
cout<<"Gelen Değer deg1="<<deg1<<"\n";
cout<<"Gelen Değer deg2="<<deg2<<"\n";
};
int main(){
yazdir("Merhaba Dünya");
yazdir("Merhaba","Dünya");
yazdir(10.55,21.25);
yazdir(10);
}
——————–
Burası tek parametre alıyorsa çalışır
Gelen Deger =Merhaba Dünya
Burası iki parametre alıyorsa çalışır
Gelen Değer deg1=Merhaba
Gelen Değer deg2=Dünya
Burası iki parametre alıyorsa çalışır
Gelen Değer deg1=10.55
Gelen Değer deg2=21.25
Burası tek parametre alıyorsa çalışır
Gelen Deger =10
——————–
Gördüldüğü üzere kodumuzu tek parametre ve iki parametre alan tipte iki adet aynı isimli generic fonksiyon kullanarak yazdık. Tek parametre ile fonksiyonumuzu çağırdığımızda
yazdir("Merhaba Dünya");
gibi
Burası tek parametre alıyorsa çalışır
Gelen Deger =Merhaba Dünya
çıktısını alıyoruz.
Aynı tipte iki parametre ile fonksiyonumuzu çağırdığımızda
yazdir("Merhaba","Dünya");
gibi
Burası iki parametre alıyorsa çalışır
Gelen Değer deg1=Merhaba
Gelen Değer deg2=Dünya
çıktısını alıyoruz. Aynı şekilde iki farklı tipte parametre alan fonksiyon ile tek tipte parametre alan fonksiyonu da birbiri ile aşırı yükleyebilirdik.
Aklıma gelmişken söylemek istedim generic fonksiyonlar şu şekilde tanımlanamazlar
template <class MYCLS>
int i;
void yazdir(MYCLS deg1){
}
template tanımı ile fonksiyon tanımı arasında herhangi bir değişken tanımı yapılamaz. Bunun yerine(zaten yukardaki kodlardan da anlamışsınızdır) tanım şu şekilde yapılmalıdır.
template <class MYCLS>
void yazdir(MYCLS deg1){
int i;
}

Bu Yayını Paylaş

Takipçi Ol

Mail adresinizi kaydedelim ilk sizin haberiniz olsun.

0 yorum:

Sponsor

Yazılarım Korunuyor

Yandex Metrica

Yandex.Metrica

Toplam Sayfa Görüntüleme Sayısı

back to top