C++ NASIL BIR PROGRAMLAMA DILIDIR?
C++ nesne yonelimli programlama tekniginin uygulanabilmesi icin C'nin genisletilmis bir bicimidir. Nesne yonelimli programlama(object oriented programming) teknigi ve C++ B.Stroustroup tarafindan gelistirilmistir. Tasarim 70'li yillarin ikinci yarisindan baslanmis olsa da bütün dünyada yayginlasmasi ve kabul gormesi 80'li yillarin sonlarina dogru mümküm olmustur. Nesne yonelimli programlama teknigi(NYP) ozellikle büyük kodlarin üstesinden gelebilmek amaciyla tasarlanmistir. Tasarimi C++ üzerinde yapilmis olmasina karsin bugün pek cok yüksek seviyeli programlama dilleri bu teknigi desteklemektedir. C++ ve nesne yonelimli programlama tekniginin en belirgin uygulama alanlarindan birisi WINDOWS altinda programlamadir. WINDOWS karmasik ve yüksek yüksek seviyeli bir isletim sistemidir. WINDOWS altinda program gelistirebilmek icin uzun kodlar yazmak gerekir. Bu nedenle WINDOWS altinda C ile degil C++ ile ve NYP teknigini kullanarak program yazmak daha etkin bir cozümdür. NYP tekniginin uygulanabilmesi icin calistigimiz sistemin kaynaklarinin yeterince genis olmasi gerekir. (Yani hizli bir mikro islemci, büyük RAM ve DISK ve iyi bir isletim sistemi)
C++'IN C'DEN FARKLILIKLARI
NYPT ILE DOGRUDAN SINIF YAPISI
ILISKISI OLMAYAN
FARLILIKLARI VE FAZLALIKLARI
Iki düzeyde degerlendirilebilir.
1-)NYPT ile dogrudan iliskisi olayan farkililiklar ve fazlaliklar
2-)Sinif yapisi
Sinif(class) C'deki yapi(struct)'lara benzer bir veri yapisidir. NYPT siniflar kullanilarak program yazilmasi teknigidir. Kursun %80'i sinif yapisinin yapisi ve kullanilmasi üzerine ayrilmistir.
C++'IN NYPT ILE DOGRUDAN ILISKISI OLMAYAN FARLILIKLARI VE FAZLALIKLARI
C++ derleyicileri C derleyicisini de icermek zorundadir. Yani C++ derleyicisi demek hem C hem de C++ derleyicisi demektir. Derleyici dosyanin uzantisina bakarak kodun C'de mi yoksa C++'ta mi yazilmis olduguna karar verir. C'de ise uzantisi c, C++'ta yazilmissa uzantisi cpp'dir.
1-)C++'ta yerel degiskenlerin bildirimleri bloklarin basinda yapilmak zorunda degildir. Standart C'de yerel degiskenler bloklarin basinda bildirilmek zorundadir. Yani küme parantezi acildiktan sonra daha hicbir fonksiyon cagirilmadan ve islem yapilmadan yapilmalidir. Bu tasarimin nedeni programcinin bildirimin yerini kolay bulabilmesini saglamaya yoneliktir. Oysa C++'ta terel degisklenler blogun herhangi bir yerinde bildirilebilir. Bir degiskenin kullanima yakin bir bolgede bildirilmesi C++ tasarimcilarina gore daha okunabilirdir. (Degisken kavrami nesne isimlerini, struct, union ve enum isimlerini ve enum sabitlerini, typedef isimlerini iceren genel bir terimdir.) O halde C++'ta yerel degiskenin faaliyet alani bildirim noktasindan blok sonuna kadar olan bolgeyi kapsar. Ne olursa olsun bir blok icerisinde ayni isimli birden fazla degisken bildirimi yapilamaz.
C++'da for dongüsünün birinci kisminda bildirim yapilabilir. Ornek olarak:
for(int i = 0,j = 20; i + j < 50; ...){ }
Tabii while dongüsünün ve if deyiminin icerisinde bildirim yapilamaz.
#include <stdio.h>
#define SIZE 100
void main(void)
{
for(int i = 0; i < SIZE; ++i)
printf("%d\n", i);
}
Boyle for dongüsünün icerisinde bildirilmis degiskenlerin faaliyet alanlari bildirildigi yerden for dongüsünün icinde bulundugu blogun sonuna kadar etkilidir. if, for, switch, while gibi deyimlerden sonra blok acilmamis olsa bile gizli bir blogun acildigi düsünülmelidir.
{
for (int i = 0; i < 100; ++i) {
for (int j = 0; j < 100; ++j) {
}
printf(%d\n", j); /*gecerli*/
}
printf("%d\n" ,i); /*gecerli*/
printf("%d\n", j); /*gecersiz*/
}
{
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 100; ++j) {
}
j = 10; /*gecersiz*/
i = 10; /*gecerli*/
}
2-)C++'ta // ile satir sonuna kadar yorumlama yapilabilir.
C++'ta /* */ yorumlama biciminin yani sira kolaylik olsun diye // ile satir sonuna kadar yorumlama bicimi de eklenmistir. Son senelerde boyle bir yorumlama bicimi standart C'de de kullanilmaya baslanmistir. Ancak ANSI C standartlarinda tanimli degildir. Tasinabilirlik bakimindan bu yorumlama bicimini standart C'de kullanmak tavsiye edilmez.
3-)C++'ta cagirilan fonksiyon eger cagiran fonksiyonun yukarisinda tanimlanmamissa fonksiyon prototipi zorunludur.
C 'de bir fonksiyonun cagirildigini goren derleyici fonksiyonun cagirilma noktasina kadar fonksiyonun tanimlamasiyla ya da prototipi ile karsilasmamissa geri donüs degerini int olarak varsayar ve kod üretir. Dolayisiyla asagidaki ornek C'de gecerlidir.
void main(void)
{
int x;
x = fonk();
}
int fonk() /*Bu durum C'de sorun olmaz ama C++'ta error verir.*/
{
}
Oysa C++'ta derleyicinin cagirilma noktasina kadar fonksiyonun tanimlamasiyla ya da prototipiyle karsilasmasi gerekir. Dolayisiyla yukaridaki kod C++'ta error'dür. (NOT: CV++ ve nesne yonelimli programlama teknigi bug olusturabilecek kodlardan kacinilmasi temeline dayandirilmistir. Yani garanti yontemler kullanilmalidir. Bu sebeple C'deki pek cok uyari C++'ta error'e donüstürülmüstür.)
4-)C++'ta farkli parametre yapilarina sahip ayni isimli birden fazla fonksiyon tanimlanabilir.
void fonk(void)
{
}
void fonk(int x)
{
}
C'de ne olursa olsun ayni isimli birden fazla fonksiyon tanimlanamaz. Oysa C++'ta parametre yapisi sayica ve/veya türce farkli olan ayni isimli birden fazla fonksiyon tanimlanabilir. Ayni isimli birden fazla fonksiyon varsa ve o fonksiyon cagirilmissa gercekte hangi fonksiyon cagirilmis oldugu cagirilma ifadesindeki parametre yapisi incelenerek belirlenir. Yani cagirilma ifadesindeki parametre sayisi ve türü hangisine uygunsa o cagirilmis olur. Geri donüs degerinin farkli olmasi ayni isimli fonksiyon yazmak icin yeterli degildir. Yani geri donüs degerleri farkli fakat parametre yapisi ayni olan birden fazla fonksiyon tanimlanamaz.
#include <stdio.h>
void fonk(int x)
{
printf("int = %d\n", x);
}
void fonk(long x)
{
printf("long = %ld\n", x);
}
void fonk(void)
{
printf("void\n");
}
void fonk(char *str)
{
puts(str);
}
void main(void)
{
fonk(); /*parametresi void olan fonksiyonu cagirir*/
fonk(10); /*parametresi int olan fonksiyonu cagirir*/
fonk(100L); /*parametresi long olan fonksiyonu cagirir*/
fonk("merhaba"); /*parametresi karakter türünden gosterici olan fonksiyonu cagirir*/
Iki anlamlilik hatasi
C++'ta pek cok durumda derleyicinin birden cok secenek arasinda karar verememesinden dolayi error durumuyla karsilasilir. Bu tür hatalara iki anlamlilik hatalari denir. Yukaridaki ornekte fonk(3.2); gibi bir cagirma yapilirsa "Ambiguity between 'fonk(int)' and 'fonk(long)'" hatasini verir. Ayni isimli birden fazla fonksiyon arasinda secme islemi ancak parametre sayilari cagilma ifadesine uygun birden fazla fonksiyon varsa gerceklesir. Parametre sayisi cagirilma ifadesine uygun tek bir fonksiyon varsa bu durumda tür uyusmasina bakilmaz. C'de oldugu gibi otomatik tür donüstürmesi yapilarak o fonksiyon cagirilir.
C++ derleyicisi ayni sayida parametrelere sahip birden fazla ayni isimli fonksiyonun bulunmasi durumunda cagirilma ifadesine tür bakimindan uygun bir fonksiyon bulamazsa bu durum iki anlamlilik hatasina yol acar. Bu durumun 3 istisnasi vardir:
1. Fonksiyon char ya da short parametreyle cagirilmissa char ya da short int parametreye sahip bir fonksiyon yok ancak int parametreye sahip bir fonksiyon varsa int parametreye sahip olan fonksiyon cagirilir.
2. Fonksiyon float parametreyle cagirilmissa ancak float parametreye sahip bir fonksiyon yok double parametreye sahip bir fonksiyon tanimlanmissa bu durumda double parametreye sahip olan fonksiyon cagirilir.
3. Fonksiyon ayni türden const olmayan bir ifadeyle cagirilmissa ancak ayni türden const parametreye sahip bir fonksiyon y,tanimlanmissa tür uyusumunun saglandigi kabul edilir ve const parametreye sahip olan fonksiyon cagirilir.
C'de ve C++'ta tanimlanan ve cagirilan bir fonksiyon ismi .obj modül icerisine yazilmak zorundadir. .obj modül standardina gore ayni isimli birden cok fonksiyon modül icerisine yazilamaz. Standart C derleyicileri fonksiyon isimlerinin basina bir _ ekleyerek obj modülün icerisine yazarlar. Oysa C++ derleyicileri fonksiyon isimlerini parametre türleriyle kombine ederek obj modül icerisine yazarlar. Bu durumda C++'ta ayni isimli farkli parametrelere sahip fonksiyonlar sanki farkli isimlere sahiplermis gibi obj modüle yazilirlar.
5-)extern "C" ve extern "C++" bildirimleri
C++'ta normal olarak bütün standart C fonksiyonlari cagirilabilir. Standart C fonksiyonlari lib dosyalarinin icerisine basinda "_" bulunarak yani standart C kurallariyla yazilmislardir. Oysa bu fonksiyonlarin C++'tan cagirilmasiyla bir uyumsuzluk ortaya cikar. Cünkü C++ derleyicisi cagirilan fonksiyonu obj modül icerisine basina "_" koyarak degil parametre türleriyle kombine ederek yani C++ kurallariyla yazar. extern "C" bildirimi bir fonksiyonun prototipinin onüne ya da bir fonksiyonun tanimlamasinin onüne getirilirse /*ornegin:
extern "C" double sqrt(double);
veya
extern "C" void fonk(void)
{
.........
}
*/
derleyici bu fonksiyonu obj modül icerisine C kurallariyla yani basina "_" koyarak yazar. Boylece C'de yazilmis olan C++'tan kullanilmasi mümkün olur. Bir grup fonksiyon yazim kolayligi saglamak icin extern "C" blogu icine alinabilir.
extern "C" {
void fonk(void);
void sample(void);
....
}
Blogun icerisinde baska bildirimler ve kodlar bulunabilir. Ancak derleyici yalnizca bu blogun icerisindeki fonksiyonlarla ilgilenir. Bu durumda standart C baslik dosyalarinin icerisinde fonksiyonlarin extern "C" bildirimiyle prototipleri yazilmis olmasi gerekir. Ayni dosya hem C hem C++'ta include edilip kullanilabildigine gore ve extern "C" bildirimi sadece C++ icin gecerliyse bir problem ortaya cikmaz mi? Bu problem onceden tanimlanmis cplusplus sembolik sabitiyle cozümlenmistir:
#ifdef cplusplus
extern "C" {
#endif
.....
.....
.....
.....
.....
.....
#ifdef cplusplus
}
#endif
Bir de extern "C++" bildirimi vardir. Bu bildirim fonksiyon isimlerinin C++ kurallarina gore obj modülün icerisine yazilacagini anlatir. Zaten fonksiyonlar default olarak bu kurala gore yazilirlar. Bu bildirim ileriye dogru uyumu saglamak icin düsünülmüstür. Su anda bir kullanim gerekcesi yoktur.
6-)C++'ta dinamik bellek yonetimi new ve delete isimli iki operatorle yapilir.
Mademki C++ icerisinde bütün standart C fonksiyonlari kullanilabiliyor, o halde dinamik bellek yonetimi malloc, claloc, realloc ve free fonksiyonlariyla yapilabilir. Ancak bu fonksiyonlar nesne yonelimli programlama teknigini uygulayabilmek icin tasarlanmamistir. Bu yüzden C++'ta yeni bir teknik kullanilmaktadir. C++'ta dinamik olarak tahsis edilme potansiyelindeki bos bolgelere free store denilmektedir(standart C'de heap denir).