C++’da, nesneye yönelik programlama çerçevesinde çalışma zamanında çok biçimlilik özelliğini desteklemek için Çalışma zamanı veri türü tanımlama (run-time type identification - RTTI) ve dört adet geçici veri türü değiştirme (casting) işlemcisi kullanılır. Çalışma zamanı veri türü tanımlama özelliği, bir programın çalışması esnasında bir nesnenin veri türünü belirlemek için kullanılır. Geçici veri türü değiştirme işlemcileri ise, daha kontrollü işlem yapma olanağı sağlar.
C++’da, bir sınıf türetilen sınıflar sisteminde ana sınıf işaretçileri ve sanal fonksiyonları kullanarak çok biçimlilik kuralına uygun uygulamalar geliştirilebilir. Ana sınıf işaretçileri, ana sınıftan oluşturulan veya ana sınıftan türetilen sınıflardan oluşturulan herhangi bir nesneyi gösterebileceğinden, herhangi bir anda bir ana sınıf işaretçisinin hangi nesneyi göstereceği önceden bilinmeyebilir. Bu belirsizliği ortadan kaldırmak için, çalışma zamanı veri türü tanımlama özelliği kullanılır.
Bir nesnenin veri türünü elde etmek için, aşağıda iki farklı genel yapısı verilen ve <typeinfo>
başlık dosyasında yer alan typeid işlemcisini kullanabiliriz.
typeid(değişken-adı)
typeid(veri-türü-adı)
değişken-adı: Veri türü elde edilecek olan değişken veya nesne adını gösterir.
veri-türü-adı: Veri türü elde edilecek olan veri türü adını gösterir.
typeid, değişkenin veri türünü gösteren type_info veri türünden bir referans geri döndürür.
type_info sınıfı içinde yer alan public fonksiyonlar aşağıdadır:
bool operator==(const type_info &ti)
bool operator!=(const type_info &ti)
bool before(const type_info &ti)
const char* name()
- == ve != işlemcileri veri türlerinin karşılaştırılması için kullanılır.
- Eğer çağrılan değişken parametre olarak kullanılan değişkenden önce geliyorsa, before() fonksiyonu doğru bir değer döndürür.
- name() fonksiyonu veri türünün adını gösteren bir işaretçi geri döndürür.
typeid işlemcisinin değişken adı ile kullanılması
Şimdi, typeid işlemcisinin kullanılmasını bir örnek üzerinde incelemeye çalışalım:
Örnek
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
class sinif {
private:
int priidana;
protected:
int proidana;
public:
int pubidana;
void deger_ata(int pid1, int pid2, int pid3)
{
priidana = pid1; proidana = pid2; pubidana = pid3;
cout << "sinif değişkenlerine değer atama: " << priidana << " " << proidana << " " << pubidana << "\n";
}
void deger_goster()
{
cout << "sinif değişken değerleri: " << priidana << " " << proidana << " " << pubidana << "\n";
}
};
template <typename T> void bg_getname(string name, T& object)
{
// RTTI sembollerini orjinal C++ kaynak kod tanımlayıcılarına dönüştürme
cout << name << " veri türü: " << abi::__cxa_demangle(typeid(object).name(), 0, 0, 0) << "\n";
}
int main(void)
{
sinif *pnes, nes;
int id;
float fd;
char *cp;
pnes = &nes
pnes->deger_ata(17, 874, 1345);
pnes->deger_goster();
bg_getname("nes", nes);
bg_getname("pnes", pnes);
bg_getname("id", id);
bg_getname("fd", fd);
bg_getname("cp", cp);
return 0;
}
Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:
1
2
3
4
5
6
7
8
9
sinif değişkenlerine değer atama: 17 874 1345
sinif değişken değerleri: 17 874 1345
nes veri türü: sinif
pnes veri türü: sinif*
id veri türü: int
fd veri türü: float
cp veri türü: char*
Program, birer adet private, protected ve public int değişken ile bu değişkenlere deger atayan ve atanan değerleri ekranda gösteren iki adet fonksiyon içeren sinif adlı bir sınıf bildirimi yapar. Bu sınıftan bir işaretçi ve nesne oluşturduktan sonra nesnenin adresini işaretçiye atar. Ayrıca, birer adet int ve float değişken ile char bir işaretçi bildirimi yapar. Sınıf işaretçisi yoluyla sınıf kopyası içindeki değişkenlere deger_ata() fonksiyonu ile değer atar ve atadığı değerleri deger_goster() fonksiyonu ile ekrana yazar.
Sınıftan oluşturulan nesne ve işaretçi ile diğer değişkenlerin veri türlerini bg_getname() fonksiyonu içindeki typeid işaretçisi ile ekrana yazar.
C++’da, RTTI sembolleri gibi tanımlayıcıların orijinal C++ kaynak kod tanımlayıcılarına dönüştürülmesine ayrıştırma adı verilir. Bu programda, veri türü isimlerinin tam olarak gösterilmesi için __cxa_demangle() fonksiyonu ile ayrıştırma işlemi yapılmaktadır.
Şimdi, type_info sınıfı içinde yer alan işlemci fonksiyonlarının kullanılmasını bir örnek üzerinde incelemeye çalışalım:
Örnek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <typeinfo>
using namespace std;
int main(void)
{
int id1, id2;
float fd;
if(typeid(id1) == typeid(id2)) cout << "id1 ve id2 veri türleri aynıdır!" << "\n";
if(typeid(id1) != typeid(fd)) cout << "id1 ve fd veri türleri farklıdır!" << "\n";
return 0;
}
Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:
1
2
3
4
id1 ve id2 veri türleri aynıdır!
id1 ve fd veri türleri farklıdır!
Program, iki adet int ve bir adet float değişken bildirimi yapar. type_info sınıfı içinde yer alan işlemci fonksiyonlarını kullanarak, değişkenlerin veri türlerini karşılaştırır ve sonuçları ekrana yazar.
typeid işlemcisinin veri türü adı ile kullanılması
Şimdi, typeid işlemcisinin, veri türü adı parametre olarak geçirilerek, kullanılmasını bir örnek üzerinde incelemeye çalışalım:
Örnek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
template <typename T> void bg_getname(string name, T& object)
{
// RTTI sembollerinin orjinal C++ kaynak kod tanımlayıcılarına dönüştürme
cout << name << " veri türü: " << abi::__cxa_demangle(typeid(object).name(), 0, 0, 0) << "\n";
}
int main(void)
{
int id;
bg_getname("id", id);
if(typeid(id) == typeid(int)) cout << "id int veri değişkenidir.";
return 0;
}
Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:
1
2
3
4
id veri türü: int
id int veri değişkenidir.
Program, bir adet int değişken bildirimi yapar. Değişkenin veri türünü bg_getname() fonksiyonu içindeki typeid işaretçisi ile ekrana yazar. Sonra, typeid işaretçisini iki farklı yapıda kullanarak, değişken adını ve int veri türünü parametre olarak geçirir. Yaptığı karşılaştırma sonucunda, birbirine eşit iki değer elde ettiğinden, if koşulu gerçekleşir ve ekrana bir karakter dizisi yazar.
typeid işlemcisinin ana sınıf işaretçileri ile kullanılması
Ana sınıf işaretçileri, ana sınıftan oluşturulan veya ana sınıftan türetilen sınıflardan oluşturulan herhangi bir nesnenin adresini gösterebileceğinden, ana sınıf işaretçilerinin çalışma zamanında hangi nesneyi gösterdiğini belirlemek için, typeid işaretçisinin kullanılmasını bir örnek üzerinde incelemeye çalışalım:
Örnek
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
class sinifana {
private:
int priidana;
protected:
int proidana;
public:
int pubidana;
// Sanal fonksiyon bildirimi
virtual void deger_topla(void) {
cout << "sinifana değişken toplamları: "<< priidana + proidana + pubidana << endl;
}
void deger_ata(int pid1, int pid2, int pid3)
{
priidana = pid1; proidana = pid2; pubidana = pid3;
cout << "sinifana değişkenlerine değer atama: " << priidana << " " << proidana << " " << pubidana << endl;
}
void deger_goster()
{
cout << "sinifana değişken değerleri: " << priidana << " " << proidana << " " << pubidana << endl;
}
};
class siniftur1 : public sinifana {
private:
int priidtur1;
protected:
int proidtur1;
public:
int pubidtur1;
// Sanal fonksiyonun siniftur1 için yeniden tanımlanması
virtual void deger_topla(void) {
cout << "siniftur1 değişken toplamları: "<< priidtur1 + proidtur1 + pubidtur1 << endl;
}
void deger_ata_tur1(int pid1, int pid2, int pid3)
{
priidtur1 = pid1; proidtur1 = pid2; pubidtur1 = pid3;
cout << "siniftur1 değişkenlerine değer atama: " << priidtur1 << " " << proidtur1 << " " << pubidtur1 << endl;
}
void deger_goster_tur1() { cout << "siniftur1 değişken değerleri: " << priidtur1 << " " << proidtur1 << " " << pubidtur1 << endl; }
};
class siniftur2 : public sinifana {
private:
int priidtur2;
protected:
int proidtur2;
public:
int pubidtur2;
// Sanal fonksiyonun siniftur2 için yeniden tanımlanması
virtual void deger_topla(void) {
cout << "siniftur2 değişken toplamları: "<< priidtur2 + proidtur2 + pubidtur2 << endl;
}
void deger_ata_tur2(int pid1, int pid2, int pid3)
{
priidtur2 = pid1; proidtur2 = pid2; pubidtur2 = pid3;
cout << "siniftur2 değişkenlerine değer atama: " << priidtur2 << " " << proidtur2 << " " << pubidtur2 << endl;
}
void deger_goster_tur2() { cout << "siniftur2 değişken değerleri: " << priidtur2 << " " << proidtur2 << " " << pubidtur2 << endl; }
};
template <typename T> void bg_getname(string name, T& object)
{
// RTTI sembollerinin orjinal C++ kaynak kod tanımlayıcılarına dönüştürme
cout << name << " işaretçisinin gösterdiği nesne: " << abi::__cxa_demangle(typeid(object).name(), 0, 0, 0) << "\n";
}
int main(void)
{
sinifana *pnes_ana, nes_ana;
siniftur1 nes_tur1;
siniftur2 nes_tur2;
cout << "pnes_ana işaretçisi ile nes_ana değişkeninin sinifana elemanlarına erişimi:" << endl;
cout << "---------------------------------------------------------------------------" << endl;
pnes_ana = &nes_ana; // sinifana türünden işaretçi sinifana nesnesinin adresini gösteriyor.
bg_getname("pnes_ana", *pnes_ana);
pnes_ana->deger_ata(17, 874, 1345);
pnes_ana->deger_goster();
pnes_ana->deger_topla(); // sinifana sanal fonksiyonuna erişim.
cout << endl << "nes_tur1 değişkeninin siniftur1 elemanlarına erişimi:" << endl;
cout << "-----------------------------------------------------" << endl;
nes_tur1.deger_ata_tur1(15, 74, 384);
nes_tur1.deger_goster_tur1();
pnes_ana = &nes_tur1; // sinifana türünden işaretçi siniftur1 nesnesinin adresini gösteriyor.
bg_getname("pnes_ana", *pnes_ana);
pnes_ana->deger_topla(); // Burada işaretçinin siniftur1 fonksiyonuna erişmesinin nedeni fonksiyonun sanal olarak tanımlanması
cout << endl << "nes_tur2 değişkeninin siniftur2 elemanlarına erişimi:" << endl;
cout << "-----------------------------------------------------" << endl;
nes_tur2.deger_ata_tur2(95, 291, 752);
nes_tur2.deger_goster_tur2();
pnes_ana = &nes_tur2; // sinifana türünden işaretçi siniftur2 nesnesinin adresini gösteriyor.
bg_getname("pnes_ana", *pnes_ana);
pnes_ana->deger_topla(); // Burada işaretçinin siniftur2 fonksiyonuna erişmesinin nedeni fonksiyonun sanal olarak tanımlanması
return 0;
}
Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pnes_ana işaretçisi ile nes_ana değişkeninin sinifana elemanlarına erişimi:
---------------------------------------------------------------------------
pnes_ana işaretçisinin gösterdiği nesne: sinifana
sinifana değişkenlerine değer atama: 17 874 1345
sinifana değişken değerleri: 17 874 1345
sinifana değişken toplamları: 2236
nes_tur1 değişkeninin siniftur1 elemanlarına erişimi:
-----------------------------------------------------
siniftur1 değişkenlerine değer atama: 15 74 384
siniftur1 değişken değerleri: 15 74 384
pnes_ana işaretçisinin gösterdiği nesne: siniftur1
siniftur1 değişken toplamları: 473
nes_tur2 değişkeninin siniftur2 elemanlarına erişimi:
-----------------------------------------------------
siniftur2 değişkenlerine değer atama: 95 291 752
siniftur2 değişken değerleri: 95 291 752
pnes_ana işaretçisinin gösterdiği nesne: siniftur2
siniftur2 değişken toplamları: 1138
Program, sinifana türünden pnes_ana adlı bir işaretçi ve nes_ana adlı bir nesne ile siniftur1 türünden nes_tur1 adlı ve siniftur2 türünden nes_tur2 adlı bir nesne oluşturur. Her üç sınıf içinde de private, protected ve public olmak üzere üç adet değişken ve bu değişkenlere değer atayan, ekranda gösteren ve değerlerini toplayan biri sanal olmak üzere üç adet fonksiyon tanımlar.
İlk olarak, nes_ana nesnesinin bellek adresini pnes_ana işaretçisine atar. Sonra, pnes_ana işaretçisinin adresini gösterdiği nesnenin veri türü olan sinifana sınıfını ekrana yazar. Bu işaretçi ile, sinifana içindeki deger_ata() ve deger_goster() fonksiyonları ile sinifana içindeki değişkenlere birer değer atar ve ekrana yazar. İşaretçi ile deger_topla() sanal fonksiyonunu kullanarak, sinifana içindeki değişken değerlerini toplar.
İkinci safhada, nes_tur1 nesnesi yoluyla siniftur1 içindeki deger_ata_tur1() ve deger_goster_tur1() fonksiyonları ile siniftur1 içindeki değişkenlere birer değer atar ve ekrana yazar. Nes_tur1 nesnesinin bellek adresini pnes_ana işaretçisine atar. Sonra, pnes_ana işaretçisinin adresini gösterdiği nesnenin veri türü olan siniftur1 sınıfını ekrana yazar. İşaretçi ile siniftur1 içindeki deger_topla() sanal fonksiyonunu kullanarak, siniftur1 içindeki değişken değerlerini toplar.
Son olarak, nes_tur2 nesnesi yoluyla siniftur2 içindeki deger_ata_tur2() ve deger_goster_tur2() fonksiyonları ile siniftur2 içindeki değişkenlere birer değer atar ve ekrana yazar. Nes_tur2 nesnesinin bellek adresini pnes_ana işaretçisine atar. Sonra, pnes_ana işaretçisinin adresini gösterdiği nesnenin veri türü olan siniftur2 sınıfını ekrana yazar. İşaretçi ile siniftur2 içindeki deger_topla() sanal fonksiyonunu kullanarak, siniftur2 içindeki değişken değerlerini toplar.
Her üç sınıf içinde ayrı ayrı tanımlanmış olan deger_topla() sanal fonksiyonu, sinifana sınıfı türünden tanımlanmış işaretçiye her sınıftan oluşturulmuş nesnelerin bellek adresleri atandığında, işaretçinin her sınıfın sanal fonksiyonuna erişerek işlem yapmasını sağlar. Ana sınıf olan sinifana işaretçisi ile sanal fonksiyon çağrıldığında, derleyici ana sınıf veya türetilmiş sınıf içindeki sanal fonksiyonlardan hangisini kullanacağına çalışma zamanında karar verir. Bu özelliğe çalışma zamanı çok biçimliliği (Runtime Polymorphism) denir.
Diğer taraftan, sinifana sınıfı türünden tanımlanmış işaretçiye türetilen sınıflardan oluşturulmuş nesnelerin bellek adresleri atansa bile, işaretçi sanal fonksiyonlar dışındaki elemanlara erişim sağlayamaz.
typeid işlemcisinin sınıf nesne referansları ile kullanılması
Ana sınıftan oluşturulan veya ana sınıftan türetilen sınıflardan oluşturulan herhangi bir nesnenin referans değerini typeid işlemcisine aktardığımızda, typeid işlemcisi nesnenin veri türünü geri döndürür.
Şimdi, bir önceki programı, sadece sınıflardan oluşturulan nesnelerle işlem yapılacak ve bu nesnelerin referans değerlerini typeid işlemcisine aktaracak şekilde yeniden düzenleyerek, incelemeye çalışalım:
Örnek
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
class sinifana {
private:
int priidana;
protected:
int proidana;
public:
int pubidana;
// Sanal fonksiyon bildirimi
virtual void deger_topla(void) {
cout << "sinifana değişken toplamları: "<< priidana + proidana + pubidana << endl;
}
void deger_ata(int pid1, int pid2, int pid3)
{
priidana = pid1; proidana = pid2; pubidana = pid3;
cout << "sinifana değişkenlerine değer atama: " << priidana << " " << proidana << " " << pubidana << endl;
}
void deger_goster()
{
cout << "sinifana değişken değerleri: " << priidana << " " << proidana << " " << pubidana << endl;
}
};
class siniftur1 : public sinifana {
private:
int priidtur1;
protected:
int proidtur1;
public:
int pubidtur1;
// Sanal fonksiyonun siniftur1 için yeniden tanımlanması
virtual void deger_topla(void) {
cout << "siniftur1 değişken toplamları: "<< priidtur1 + proidtur1 + pubidtur1 << endl;
}
void deger_ata_tur1(int pid1, int pid2, int pid3)
{
priidtur1 = pid1; proidtur1 = pid2; pubidtur1 = pid3;
cout << "siniftur1 değişkenlerine değer atama: " << priidtur1 << " " << proidtur1 << " " << pubidtur1 << endl;
}
void deger_goster_tur1() { cout << "siniftur1 değişken değerleri: " << priidtur1 << " " << proidtur1 << " " << pubidtur1 << endl; }
};
class siniftur2 : public sinifana {
private:
int priidtur2;
protected:
int proidtur2;
public:
int pubidtur2;
// Sanal fonksiyonun siniftur2 için yeniden tanımlanması
virtual void deger_topla(void) {
cout << "siniftur2 değişken toplamları: "<< priidtur2 + proidtur2 + pubidtur2 << endl;
}
void deger_ata_tur2(int pid1, int pid2, int pid3)
{
priidtur2 = pid1; proidtur2 = pid2; pubidtur2 = pid3;
cout << "siniftur2 değişkenlerine değer atama: " << priidtur2 << " " << proidtur2 << " " << pubidtur2 << endl;
}
void deger_goster_tur2() { cout << "siniftur2 değişken değerleri: " << priidtur2 << " " << proidtur2 << " " << pubidtur2 << endl; }
};
template <typename T> void bg_getname(string name, T& object)
{
// RTTI sembollerinin orjinal C++ kaynak kod tanımlayıcılarına dönüştürme
cout << name << " nesnesinin veri türü: " << abi::__cxa_demangle(typeid(object).name(), 0, 0, 0) << "\n";
}
int main(void)
{
sinifana nes_ana;
siniftur1 nes_tur1;
siniftur2 nes_tur2;
cout << "nes_ana değişkeninin sinifana elemanlarına erişimi:" << endl;
cout << "---------------------------------------------------" << endl;
bg_getname("nes_ana", nes_ana);
nes_ana.deger_ata(17, 874, 1345);
nes_ana.deger_goster();
nes_ana.deger_topla(); // sinifana sanal fonksiyonuna erişim.
cout << endl << "nes_tur1 değişkeninin siniftur1 elemanlarına erişimi:" << endl;
cout << "-----------------------------------------------------" << endl;
bg_getname("nes_tur1", nes_tur1);
nes_tur1.deger_ata_tur1(15, 74, 384);
nes_tur1.deger_goster_tur1();
nes_tur1.deger_topla(); // siniftur1 sanal fonksiyonuna erişim
cout << endl << "nes_tur2 değişkeninin siniftur2 elemanlarına erişimi:" << endl;
cout << "-----------------------------------------------------" << endl;
bg_getname("nes_tur2", nes_tur2);
nes_tur2.deger_ata_tur2(95, 291, 752);
nes_tur2.deger_goster_tur2();
nes_tur2.deger_topla(); // siniftur2 sanal fonksiyonuna erişim
return 0;
}
Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
nes_ana değişkeninin sinifana elemanlarına erişimi:
---------------------------------------------------
nes_ana nesnesinin veri türü: sinifana
sinifana değişkenlerine değer atama: 17 874 1345
sinifana değişken değerleri: 17 874 1345
sinifana değişken toplamları: 2236
nes_tur1 değişkeninin siniftur1 elemanlarına erişimi:
-----------------------------------------------------
nes_tur1 nesnesinin veri türü: siniftur1
siniftur1 değişkenlerine değer atama: 15 74 384
siniftur1 değişken değerleri: 15 74 384
siniftur1 değişken toplamları: 473
nes_tur2 değişkeninin siniftur2 elemanlarına erişimi:
-----------------------------------------------------
nes_tur2 nesnesinin veri türü: siniftur2
siniftur2 değişkenlerine değer atama: 95 291 752
siniftur2 değişken değerleri: 95 291 752
siniftur2 değişken toplamları: 1138
Program, sinifana türünden nes_ana adlı bir nesne ile siniftur1 türünden nes_tur1 adlı ve siniftur2 türünden nes_tur2 adlı bir nesne oluşturur. Her üç sınıf içinde de private, protected ve public olmak üzere üç adet değişken ve bu değişkenlere değer atayan, ekranda gösteren ve değerlerini toplayan biri sanal olmak üzere üç adet fonksiyon tanımlar.
İlk olarak, nes_ana nesnesinin veri türü olan sinifana sınıfını ekrana yazar. Bu nesne yoluyla, sinifana içindeki deger_ata() ve deger_goster() fonksiyonları ile sinifana içindeki değişkenlere birer değer atar ve ekrana yazar. Sonra, deger_topla() sanal fonksiyonunu kullanarak, sinifana içindeki değişken değerlerini toplar.
İkinci safhada, nes_tur1 nesnesinin veri türü olan siniftur1 sınıfını ekrana yazar. Bu nesne yoluyla, siniftur1 içindeki deger_ata_tur1() ve deger_goster_tur1() fonksiyonları ile siniftur1 içindeki değişkenlere birer değer atar ve ekrana yazar. Sonra, siniftur1 içindeki deger_topla() sanal fonksiyonunu kullanarak, siniftur1 içindeki değişken değerlerini toplar.
Son olarak, nes_tur2 nesnesinin veri türü olan siniftur2 sınıfını ekrana yazar. Bu nesne yoluyla, siniftur2 içindeki deger_ata_tur2() ve deger_goster_tur2() fonksiyonları ile siniftur2 içindeki değişkenlere birer değer atar ve ekrana yazar. Sonra, siniftur2 içindeki deger_topla() sanal fonksiyonunu kullanarak, siniftur2 içindeki değişken değerlerini toplar.
typeid işlemcisinin şablon sınıf nesneleri ile kullanılması
Şimdi, şablon sınıflarda typeid işlemcisinin kullanılmasını bir örnek üzerinde incelemeye çalışalım:
Örnek
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <cxxabi.h>
using namespace std;
template <typename t> class sinif {
private:
t priid;
protected:
t proid;
public:
t pubid;
void deger_ata(t pid1, t pid2, t pid3)
{
priid = pid1; proid = pid2; pubid = pid3;
cout << "sinif değişkenlerine değer atama: " << priid << " " << proid << " " << pubid << endl;
}
void deger_goster()
{
cout << "sinif değişken değerleri: " << priid << " " << proid << " " << pubid << endl;
}
};
template <typename T> void bg_getname(string name, T& object)
{
// RTTI sembollerinin orjinal C++ kaynak kod tanımlayıcılarına dönüştürme
cout << name << " veri türü: " << abi::__cxa_demangle(typeid(object).name(), 0, 0, 0) << "\n";
}
int main(void)
{
sinif <int> nes1;
bg_getname("nes1", nes1);
nes1.deger_ata(121, 745, 1059);
nes1.deger_goster();
sinif <float> nes2;
bg_getname("nes2", nes2);
nes2.deger_ata(72.21f, 1084.47f, 1273.85f);
nes2.deger_goster();
return 0;
}
Yukarıdaki programı derleyip çalıştırdığımızda, aşağıdaki ifadeleri ekrana yazar:
1
2
3
4
5
6
7
8
nes1 veri türü: sinif<int>
sinif değişkenlerine değer atama: 121 745 1059
sinif değişken değerleri: 121 745 1059
nes2 veri türü: sinif<float>
sinif değişkenlerine değer atama: 72.21 1084.47 1273.85
sinif değişken değerleri: 72.21 1084.47 1273.85
Program, önce tek bir veri türünün parametre olarak geçirildiği bir sınıf tanımlar. Tanımladığı sinif türünden nes1 nesnesini oluştururken int veri türünü parametre olarak sınıfa geçirir. Sınıf içindeki deger_ata() fonksiyonu ile tüm değişkenlere bir değer atar ve deger_goster() fonksiyonu ile değişken değerlerini ekrana yazar. Aynı işlemleri nes2 nesnesini tanımlarken float veri türü ile yapar. Her veri türüne ait sınıftan bir nesne oluşturduktan sonra, her nesnenin veri türünü ekran yazar.