Posted by: okipuki on: Temmuz 19, 2008
Visual C++, C++ ile program yazmak üzere donatılmış, görsel yönelimli bir yazılım geliştirme ortamıdır. C++ ya da C dilinde yazılması olası olan her türlü programı Visual C++ ile yazabilirsiniz. C++, C’nin üst kümesidir. C dilinin geliştirilmesi ile oluşturulmuştur. Bu dil C’nin kapsamakta olduklarına ek olarak nesneye dayalı programlamayı da (OOP – Object Oriented Programming) destekler.
C++ dilinin pek çok özelliği bir şekilde OOP ile ilgilidir. Fakat şunu anlamalıyız: C++’ı, nesneye dayalı olan ve olmayan programları yazmak için kullanabiliriz. Onu nasıl kullanacağımız tamamen bize bağlıdır.
MFC, Visual C++ kullanarak Windows uygulamaları yazmak için yeğlenen yoldur. MFC, özelleştirmeniz için hazır olan, işler durumdaki bir sosyal windows uygulamalarından oluşan, C++ sınıflarının bir kümesidir. Başlangıç dosyaları kümesi oluşturan MFC AppWizard ile işe başlarsınız. Daha sonra uygulamanızı eşsiz yapan özellikleri gerçekleştirecek kodları eklersiniz. Kısaca MFC hazırlanmış kod kütüphanesidir.
Visual C++’ı yükledikten sonra, programı Windows başlat menüsünden çalıştırabilirsiniz.
Aşağıda Visual C++ program ekranın bir görüntüsü bulunmaktadır.
Şekil 1.1 Microsoft Visual C++ Ekran Görüntüsü
Visual C++’ çalıştırdıktan sonra, yeni bir proje başlatmanız ya da var olan bir projeyi yüklemeniz gerekmektedir. Proje nasıl oluşturulur veya nasıl açılır bunu daha sonra ele alacağız.
Şimdi Visual C++ programından yardım almak için ne yapmamız gerekiyor buna bir göz atalım.
Visual C++ pogramının gelişmiş bir yardım alma sistemi vardır. Visual C++’ta programlama yaparken yardım almanın dört yolu vardır.
F1 Help, Bu yardım almanın en hızlı yoludur. Bir sözcüğü tıklayarak, bir tümceyi vurgulayarak yada bir hata iletisini tıklayarak F1 tuşuna basmak yeterlidir. Seçilen konu hakkındaki yardım metni karşımıza çıkacaktır.
Help dizini, Help dizinde aradığınız konular başlıklar arasında veya alt başlıklarında düzenli bir şekilde bulunmaktadır.
Tüm metni arama düzeneği, aradığınız bir kelimeyi tüm yardım konularında bulmanızı sağlar.
İçindekiler, Help’in ayrıntılı bir içindekiler tablosu vardır. İçindekiler kısmını kullanmak bir kitap okumak yada gözden geçirmek gibidir.
Visual C++’ta bir çalışma alanına birden çok proje yerleştirmek mümkündür.
Projeler: Yeni bir programa başladığınızda, ilk yapacağınız iş File menüsünden New komutunu seçerek onun için bir proje yaratmaktır. Proje dosyası, programınızın hangi kaynak kod dosyalarını ve kaynak dosyalarını kullandığı ve Visual C++’ın programınızı oluşturma biçimini denetlemek için belirttiğiniz tüm ayarlar hakkındaki bilgileri sağlar. Visual C++ oluşturma sistemi, çalıştırılabilir bir program yaratmak için dosyalarınızı derleyip bağlantılandırırken bu bilgiyi kullanır.
Çalışma Alanları: Bir proje oluşturduğunuzda , varsayılan değer olarak birde çalışma alanı dosyası oluşturulur. Bu dosya projeismi.dsw dosyasıdır. Bu dosyada Visual C++ pencerelerinin açık olduğunu ve konumlarını ayrıca çalışma alanı için belirttiğiniz ayarlar tutulmaktadır.
Uygulamanızı geliştirmek için şu adımları izlemeniz gerekecektir.
Şimdi bu adımları başlıklar altında inceleyelim.
Bir proje oluşturmak için aşşağıdaki adımları yapmanız gerekir.
Visual C++ size hazır bir proje oluşturacaktır. Siz bu proje üzerinde düzenlemeler yaparak
kendi projenizi oluşturacaksınız. Yeni bir proje oluşturup bunların üzerinde düzenleme yapmayı Merhaba projesinde ayrıntılı olarak anlatacağız.
Visual C++ Location kutusnda seçmiş olduğunuz dizine gerekli kaynak dosyalarını oluşturmuş olmalıdır bu dosyaları incelemek ve düzenleme yapmak için Çalışma Alanı Penceresini kullanmayı öğrenmemiz gerekecek.
Şekil 1.2 Çalışma Alanı Penceresi
Çalışma Alanı Penceresinde 3 Sekme bulunmaktadır.
FileView Sekmesini Kullanmak: Kaynak kodu dosyalarını (.cpp), üstbilgi dosyalarını (.h) ve kaynak dosyalarını (.rc) içeren klasör kümesini görmek için WorkSpace penceresinden FileView sekmesini tıklayın. Bu listeden istediğiniz dosyayı çift tıklayarak görüntülenmesini sağlayabilirsiniz.
ResourceView Sekmesini Kullanmak: Menüler, iletişim kutuları, formlar, araç çubukları, simgeler ve iconlar burda listelenmektedir. Yaptığınız seçime göre yapı çalışma alanında gösterilecektir.
Projeler genellikle 3 çeşit kaynak dosya türü içerir. Üst bilgi dosyaları (.h uzantılı), kaynak kodu dosyaları (.cpp uzantılı) ve kaynak dosyaları (.rc uzantılı). Şimdi bu dosyaları Projenize ekleme nasıl yapılıyor buna bakalım.
Yeni bir .h, .cpp dosyası eklemek için File menüsünden New seçeneğini seçin. New iletişim kutusunun Files sekmesini seçtikten sonra .h dosyası için Header File, .cpp için Source File dosya tipini seçin eklemek istediğiniz projeyi seçin eğer o anda çalıştığınız projeye eklemek istiyorsanız Add to Project seçeneğini seçmeyin. File Name kutusuna dosya ismini yazın ve kaydetmek istediğiniz dizini location kutusuna girin ve OK tıklayın.
Varolan bir dosyayı eklemek için Project menüsünden Add to Project seçeneğini ve Files seçeneğini seçin. Açılan dialog penceresinden dosyanızı seçip OK tıklayın.
Böylece dosyalarınız projenize dahil edilecektir. FileView listesine dosyanızın eklendiğini göreceksiniz.
Dosya silmek için, FileView listesinde silmek istediğiniz dosyayı seçin ve Delete tuşuna basın.
C++ kaynak kodunu düzenlemek, Kodunu düzenlemek istediğiniz dosyayı FileView penceresinde çift tıklayarak açın. Dosyanız Source Code düzenleyicisinde açılacaktır.
Source Code düzenleyicisi, pogramdaki çeşitli söz dizim öğelerini, kayak dosyalarının daha kolay okunabilmesini sağlayan renklerle otomatik olarak kodlar. Bu sayede kaynak kodlarınızın okunabilirliği artmaktadır.
Kaynakları düzenlemek, Kanakları düzenlemek için ResorceView listesinden düzenleyeceğiniz yapıyı seçmelisin bu bir menü, toolbar, iletişim kutusu vs. olabilir. Her bir kaynak türü için farklı bir düzenleyici vardır. Bu düzenleyiciler sayesinde yapınızı istediğiniz gibi düzenleyebilme imkanınız vardır.
Programınızı geliştirirken genellikle Debug build yapısıyla çalışacaksınız. Debug ve Release oluşturmaları arasında geçiş yapmak için projenizin etkin yapısını değiştirmeniz gerekir. Bunu yapmak için Build menüsünden Set Active Project Configuration iletişim kutusunu açın. Bu kutudan Win32 Debug yada Win32 Release’i seçin. Sonra OK tıklayın.
Projeyi oluşturmak derlemek ve exe dosyası haline getirmektir. Visual C++, programınızı tek bir komutla derleyip bağlamanıza olanak sağlayan bir oluşturma sistemine sahiptir.
Projeyi oluşturmak için Build menüsünden projeadı.exe’yi tıklayın ya da F7 tuşuna basın. Program size projenizi derleyip Debug klasörüne kaynak dosyalarla birlikte exe dosyanızı oluşturacaktır.
Projeyi çalıştırmak için Build menüsünden Execute projeadı.exe komutunu seçin ya da Ctrl + F5 tuşlarına basın. Projeniz çalıştırılarak ekrana gelecektir.
Şimdi öğrendiklerimizi uygulamak ve gerçek bir proje üzerinde çalışmak için Merhaba isimli projemizi oluşturalım.
MERHABA PROJEMİZİ OLUŞTURALIM
Merhaba isimli projemizi oluşturup şimdiye kadar anlattıklarımızı uygulamak için aşşağıdaki işlemleri adım adım uygulayın.
Şimdiye kadar yapmış olduğumuz adımlarda projemizin ana yapısını oluşturmuş bulunmaktayız şimdi yapmamız gereken, projemizin yapacağı işlevi kodlayarak projemize ilave etmek. Bunun için yeni bir kaynak kodu dosyası oluşturmalıyız. Dosyayı oluşturmak için aşağıdaki adımları uygulayın.
OK butonuna tıkladıktan sonra Merhaba.cpp dosyanız projenize eklenmiş olacaktır. Şimdi bu kaynak dosyamıza gerekli olan kodları gireceğiz. Aşağıdaki kodu Merhaba.cpp dosyasına girip dosyanızı kaydedin. Noktalı virgül işaretlerine dikkat edin.
// Merhaba Programı İçin Kaynak Kod Dosyası
#include <iostream>
using namespace std;
int main()
{
cout << “Merhaba Bu Ilk Programimiz” << endl;
return 0;
}
Kaynak dosyamızı oluşturduğumuza göre şimdi projemizi derleyip çalıştrıabiliriz. Projemizi derlemek için aşağıdaki işlemleri yapın.
Küçük bir program oluşturup çalıştırmayı öğrendik. Şimdi C++ temel öğelerini öğrenelim.
VİSUAL C++ TEMELLERİ
Bu kısımda C++ programlama dilinin en çok kullanılan öğelerini ele alacağız. Yazım kurallarından, değişkenlere, dizilerden döngü ifadelerine bir çok öğeyi öğrenmiş olacaksınız.
Aşağıda bu öğeler listelenmiştir.
C++ Açıklamaları
Açıklamalar programınızın okunabilirliğini artırmak ve daha sonra düzenleme yapılabileceği düşüncesiyle kodlar arasına konulan notlardır. Açıklamalar (//) iki eğri çizgiden sonra yapılır.
// Bu C++’ta bir açıklamadır.
Açıklamalar bir kod satırından sonrada yapılabilir.
Char* szCpp = “C++”; // Deşiken Bildirimi
Birden fazla satırlı açıklamalar yapmak için açıklama satırının başına /* sonuna ise */ işaretleri konmalıdır.
/* Açıklama
iki satırda */
Önişlemci Yönergeleri
Önişlemci, derleyiciden önce çalışan bir programdır. Derleyici, aşağıdakiler gibi önişlemci yönergelerine bakar.
#include <iostream.h>
#define Numara 1
include komutu ile bir dosya kaynak kodu dosyalarına ilave edilir. Bir dosyayı dahil etmenin amacı, orada tanımlanan işlevleri, sınıfları, değişkenleri ve diğer kod öğelerini kullanmaktır.
C++ Değişmezleri
Bir #define yönergesi, önişlemciye, program dosyalarının her yerinde simgeyi değeriyle değiştirmesini söyler. Tanımlama aşağıdaki kod satırındaki gibi yapılır.
#define Numara 1 // Numara değişkenin değeri bir olacaktır
C++’ta değişmezlerin (sabitlerin) tanımlanmasının diğer bir yolu ise const komutunun kullanılması ile yapılır.
Const int Numara = 1;
Bu komut satırı Numara adında bir değişken oluşturur bu değişkenin değeri ise 1’dir.
C++ Anahtar Sözcükleri
C++, kendi kullanımı için bazı tanıtıcıları ayırır. Örneğin for, if ve int birkaç anahtar sözcüktür. Değişkenler, işlevler gibi şeyler için anahtar sözcüklerini ad olarak kullanamazsınız.
Hazır Bilgiler
Hazır bilgiler değişmezlerdir ve bellekte saklansalar da, adreslerine erişemezsiniz.
C++’ta, yazdırılamayan karakterleri temsil edebilirsiniz.
Deyimler
Noktalı virgül imiyle biten tek bir bildiri, komut ya da hesaplamadır. Önişlemci yönergeleri bu türde deyimler değildir.
const char* PROGRAM_ADI = “Microsoft Visual C++”;
char* szVersion = “6.0”;
İlk komut satırı PROGRAM_ADI isimli bir sabit (değişmez) tanımlıyor ve değer ataması yapıyor. İkinci satırda ise szVersion isimli bir değişken oluşturuluyor değeri veriliyor. Bu iki komut satırı C++ için deyimlerdir.
Değişkenler ve Veri Türleri
Bir değişken (variable), bellekte programın bilgi saklaması için adlandırılmış bir bölgedir. Değişkenleri isimlendirirken tutacağı değere uygun bir isim vermeniz programın okunabilirliğini artıracaktır. Örnek bir değişken tanımı aşağıda gösterilmiştir.
char* szVersion = “Version 6.0”;
Derleyici bu komut satırını gördüğünde bellekte bir alan ayıracak bu alanı szVersion değişken ismiyle adresleyecektir. Bir değişkende en önemli şey türüdür (type). Burada szVersion char (Karakter Dizini) türündedir. Veri türleri aşağıda gösterilmiştir.
|
Tür |
Açıklama |
|
int, long, short
int n; long l; short s;
char
char c; char* string;
bool
bool b;
float, double, long double
float f; double d; long double ld;
|
Tam sayı veri türleridir. Visual C++ dilinde, int ve long 4 byte ve short 2 bytedır.
1 bit tamsayı türü olan char, karakter verisi saklar. Temsil ettiği karakter için char değişkeninin içeriği sayısal ASCII kodudur.
Tamsayı türü olsa da, Boolean gibi davranır. Olası değerler True yada False dir.
Kesirli sayılar saklayabilirler. float 4 bit double ve long double ise 8 bittir. |
Tablo 1.1 Veri Türleri
Bu veri türlerinin başına unsigned deyimi konursa pozitif değerleri tutarlar.
Bu veri türlerine ek olarak aşağıdaki türler vardır. Bu tabloda ayrıca veri türü oluşturmak için diğer yapılar gösterilmiştir.
|
Tür |
Açıklama |
|
Enum enum renk { Kirmizi Beyaz Mavi = 25 }
struct struct Ogrenci { char* szAd; int nYas; };
typedef typedef double para typedef char* string ………………… para myMaas; string szName;
pointer
reference
class
array
character string
|
Numaralandırılmış tür. C++’ta enum gerçek tür belirleyicidir. Solda bulunan renk türü gibi bir enum, renkler, haftanın günleri, vb. ilgili değişmezleri belirlemenizi sağlar.
C++ dilinde, bir struct ya da yapı tam oturmuş veri türüdür. Yapılar sınıflara cok benzer. Ogrenci myOgrenci; İnt age = myOgrenci.nYas;
Var olan türlerden kendi adlarınızı oluşturmak için typedef kullanılır. Typedef kodlarınızı daha okunabilir yapmak içindir.
İşaretçiler
Başvurular
Sınıflar
Diziler
Karakter Dizinleri |
Tablo 1.2 Veri Türleri Oluşturmak İçin Yapılar
Değişken Adlandırılırken Kullanılan Düzenler
Hungarian notation kullanarak yapılan değişken isimlendirmesi çok yaygındır. Bu isimlendirme şeklinde değişkenin veri türünün bir parçasını değişken ismine ekleme ile yapılır.
int nYas;
char* szAd;
nYas isimli değişkenin int tipte bir değişken olduğunu başındaki n harfinden anlıyoruz.
Aşağıda hangi isimlerin verildiği gösterilmiştir.
|
Hungarian Örnek |
Veri Türü |
|
b by c ya da ch d ya da dbl f ya da fl fn L ya da l n ya da i p sz str ar pt rect wnd |
bool yada BOOL BYTE char double float function long int pointer sıfır sınırlı dizin MFC String nesnesi array point rectangle window |
Tablo 1.3 Veri Türlerine Göre İsimlendirme Ekleri
Diziler
Belirtilmiş tipteki bir çok öğeyi içerebilen değişkenlere dizi denir. Dizi bildirimi aşağıdaki gibi yapılır.
int arInts[10]; //arInts isminde dizi tanımı
Burada arInts isminde 10 boyutlu bir dizi değişkeni tanımlanmıştır. Dizi değişkenleri indexi 0’dan başlayan ve belirtilmiş boyutta değer saklayabilen değişkenlerdir. Örnek olarak 5 elemanlı bir diziye 1’den 5’e kadar değer ataması yapalım.
int arInts[5];
for (int i=0: i < 5: i++)
{
arInts[i]=i+1;
}
Bu komut satırlarında for döngüsü sayesinde 5 defa komut işlenir her seferinde i değişkenin değeri bir artırılır ve i’nin bir fazlası değişkene aktarılır. Bu sayede dizimize 1’den 5’e kadar değer atamış oluruz. Çok boyutlu dizi tanımlaması aşağıdaki gibi yapılır.
int arInts[5][5];
Bu tanımlama ile arInts isminde 5’e 5 bir dizi tanımlanmış olur. Bu sayede 5’e 5 bir matrisi bu dizide saklayabiliriz.
Değişkenler İçin Bellek Ayırmak
C++ dili tanımlamalarınıza göre bellekte otomatik yer ayırır. Örneğin “Version 6.0” dizinindeki her karakter ve bir tanede boş karakteri sonlandırmak için toplam 12 bit ayırır. Her çalışan programın gerek duyduğu bellek için kullanılabilir iki bellek havuzu vardır.
Yığın, sistemin kullandığı geçici bellek alanıdır. Aslında yığın, bir karalama defteri ya da kısa vadeli bellektir.Yığında veriler en üste yerleştirilir ve alırken hep üstten alınır. Yığınlar, son giren ilk çıkar veri yapılarıdır. Son itilen öğe, ilk çıkan öğedir.
C++, yığınları çoğunlukla işlev çağrıları için kullanır. İşlev çağrıldığında, çeşitli öğeler yığının üstüne itilir. İşlevin bittiği zamanki dönüş adresi, işleve geçirilen parametrelerin tümü, işlevin verdiği sonuçlar ve hatta işlevde bildirilen yerel değişkenler yığının üstüne yerleşir. Dolayısıyla, işlev a, işlev C’yi çağıran işlev B’yi çağırdığında, yığın büyür. İşlevlerin her biri döndükçe, yığında o işleve ait öğeler silinir. Yığın küçülür.
Küme, daha kalıcı bir saklama alanıdır. Ona, uzun zamanlı bellek de diyebiliriz. Program, C++ new işlecini kullanarak küme belleği ayırır. New işlecine bir çağrı, istenilen belleği ayırır ve ona bir işaretçi gönderir. Bir değişkende, gerek duyduğunuz sürece işaretçiyi ortalıkta tutabilirsiniz. Kümede bellek ayırmak için, aşağıdaki örneklerde olduğu gibi new işlecini çağırın.
int* pInt = new int; // Kümede tek bir tamsayı
int* arInt = new int [10]; // Kümede tamsayı dizisi
new işleci, belirli bir tipteki nesne için yeterli bellek ayırır ve ayrılmış belleğe bir işaretçi gönderir.
İşlevler (Fonksiyonlar) ve Parametreler
Bir çok dilde olduğu gibi C++ dilinde, işlev, programın yaptığı bazı önemli işlemleri korur. İşlevler, programın çeşitli yerlerinden defalarca çağırabileceğiniz. Öznel ve bağımsız kod yığınlarıdır. Hatta bazen bir işlevi diğer progralarda da yeniden kullanabilirsiniz.
İşlevler, birkaç değişik türde olabilir.
· Bazı işlevler parametreler (Parameters) alır. Bazıları almaz paramatreler, işleve geçirdiğiniz ve işlevin çalışmasının temelini oluşturan değerlerdir. Parametreler, çeşitli girdi verisi üzerinde işlem yapmayı geçerli kılarak, işlevin daha genel amaçlı yaparlar.
· Bazı işlevler sonuç (Result) dönüşümü yapar, bazıları yapmaz. C++ dilinde, sonuç dönüşümü yapsalar da yapmasalar da bunların tümüne işlev denilmektedir.
İşlevlerin tanımı aşağıdaki gibi yapılır.
bool NumberContol (char* szTo, int nCalc);
Yukarıdaki komut satırını inceleyecek olursak. bool, fonksiyondan geri dönecek olan parametrenin tipidir. NumberControl, fonksiyonun ismidir. Parantez içindeki tanımlamalar ise fonksiyona gönderilen değerleri alan değişkenlerin tanımıdır. Geriye bir değer döndürmeyen fonksiyonlar tanımlanırken bool yerine void yazılır.
Genellikle, bir işlev herhangi bir veri tipinde sonuç alabilir. Aynı zamanda işlev, bir pointer (işaretçi), ya da reference (başvuru) döndürebilir.
Return anahtar sözcüğünü kullanarak bir sonuç alabilirsiniz. Sonuç veren bir işlevde, return’ü çağırmalısınız ve doğru tip değerini sonuç olarak belirtmelisiniz. Örneğin;
int MyFunction()
{
return 3;
}
Aynı zamanda, sonuçlanmayan return işlevleri de kullanabilirsiniz. Bu durumda dönüş değerini belirtmiyorsunuz. Return’ün kullanımının amacı, bir şey yanlış olduğunda bunu erken fark etmek ya da işlevin yürütme gerekmeyen kısmını belirtmektir.
main işlevi
C++ programlarının hepsi, main adındaki işlevi yani fonksiyonu işleyerek başlar. C++ dilindeki main işlevi, her zaman “main” adı olsada yazdığınız özel bir işlevdir.
Programın işleyiş sırasını görmek için küçük bir program yazalım ve bu programı satır satır inceleyelim.
int main ( int argc, char* argv[])
{
char* szCpp = “C++!”; // Değişken bildirimi ve değerinin ataması.
// Boolean sonucu olan bir işlevi çağırın
if (SayHello(szCpp, 2))
{
// Sonucu olmayan bir işlev çağırın
SayGoodBye();
}
return;
}
Bir programın yürütme aşamalarını görmeye çalışalım.
1. C++ bazı ön hazırlıkları yapar.
2. main yürütmeye başlar.
3. main, szCpp değişkenini bildirir ve sıfırlar. Bu, program yığınında szCpp için bellek ayırır. Belleğin toplam miktarı, sıfırlama dizininin uzunluğu ile belirlenir.
4. main, SayHello işlevlerini çağırır. SayHello’nun parametreleri SayHello’nun döndürülmüş sonucuyla (bir bool) birlikte yığına yerleştirilmiştir.
5. SayHello, ilk önce bir ileti yazdırırarak ve sonrada nCalc’ı ilgilendiren deyimi değerlendirip son olarak o değerlendirmenin sonucunu main’e döndürerek yürütür.
6. Bu arada mainde SayHelle’nun sonucu olan boolean değeri, if deyimine koşul olarak kullanılır. SayHello, true (doğru) döndürürse, if deyimi kütüğünün içindeki deyim, SayGoodBye işlevine çağrı yürütür. SayHello, false (yanlış) döndürürse, if deyimin gövdesi atlanır.
7. Bu durumda, SayGoodBye, ileti yazdırarak yürütür. Yığına yerleştirilecek parametreler, yerel değişkenler ya da işlev sonuçları yoktur. Ancak yürütmenin SayGoodBye çağrıldıktan hemen sonra main işlevine dönebilmesi için bi dönüş adresi saklanır.
8. Bu arada main işlevinde, SayGoodBye döndüğünde if deyimi tamamlanır ve if deyiminin kıvrımlı kapama ayraçlarıyla karşılaşılır.
9. main işlevi return 0 deyimine vardığında, işlev her şeyin yolunda gittiğini işaret eden 0 değerini döndürür ve bu program biter. Sorun çıkmış olsaydı, main işlevi başka bir değer döndürebilirdi.
İfadeler ve İşleçler
İfadeler
Değişkenler ve sayılar arasında matematiksel ve mantıksal ilişkiye ifade denir. Aşağıda birkaç ifade örneği gösteriliyor.
( nCalc + (nCalc * 2 )) < (24/nCalc)
//alt ifade 1 < alt ifade 2
Alt ifadelerden her biri, bir sayıya ulaşan aritmetik bir ifadedir.
İşleçler (Operatörler)
Sayılar arasındaki ilişkiyi belirleyen işaretlere işleç denir. Ayrıca işleçler matematiksel işlemleri yapmak için kullanılır. İki ifadeyi karşılaştırmak ve değer atamak için kullanılan işleçlerde vardır. C++ ta kullanılan bir çok işleç aşağıdaki tabloda örnekleriyle gösterilmiştir.
|
İşleç Kategorisi |
İşleçler |
Örnekler |
|
|
Aritmetik
Mantıksal ve ilişkisel
Çoğalma ve azaltma |
+ - * / %
< > <= >= == != && | | !
i++ ++i i— –i |
Toplama Çıkarma Çarpma Bölme Modülüs
Küçüktür Büyüktür Küçük ya da eşittir Büyük ya da eşittir Eşittir Eşit değildir Mantıksal AND Mantıksal OR Mantıksal NOT
Sonradan artırma Önceden artırma Sonradan azaltma Önceden azaltma |
2 + 3 3 – 2 3 * 4 12 / 6 7 % 2
i < 10 i > 10 i <= 10 i >= 10 i == 10 i != 10 coud1 && cond2 cond1 | | cond2 !bCondition
|
|
İşleç Kategorisi |
İşleçler |
Örnekler |
|
|
Bitwise
Atama
sizeof
Aritmetik if |
~ << >> & | ^
= = += -= *= /= %= <<= >>= &= |= ^=
sizeof
?: |
Bitwise not Ekleme işleci Ayıklama işleci Bitwise and Bitwise or Bitwise xor
Atama Bileşik atama Topla, sonra ata Çıkar, ata Çarp, ata Böl, ata Modülüs, ata Sola kaydır, ata Sağa Kaydır, ata Bitwise and,ata Bitwise or, ata Bitwise xor, ata
Veri tipinin boyutu
Aritmetik karşılaştırır |
~myInt myInt << 2 myInt >> 2 myInt & FLAG myInt | FLAG myInt ^ FLAG
x = 14 x = y = 17 x += 1 x -= 1 x *= 5 x /= 2 x %=3 vb.
Sizeof(float)
İ > j ? i : j |
Tablo 1.4 Operatörler
Öncelik Sırası
İfade değerlendirmesi sırasında, bazı C++ işleçlerinin diğerlerine göre yapılma önceliği vardır. İşlem sırası aşağıda gösterilmiştir.
· Parantez içindeki ifadeler
· Mantıksal karşılaştırmalar
· Çarpma, bölme, modülüs
· Toplama, çıkarma
Sizinde göreceğiniz gibi işlem sırasını bizim belirlememiz için parantezleri kullanmalıyız bu kullanım sırasında yapmak istediğiniz ilk işlemi en iç parantez haile getirmeniz gerekir. Bunu daha iyi anlamak için bir örnek yapalım.
Yapmak istediğimiz x değişkeninden 2 çıkarıp çıkan sonucun karesini aldıktan sonra x – 5 ifadesine bölme işlemini yaptıralım . Bu işlemi aşağıdaki gibi yaparsak çok yanlış bir sonuç alırız.
Sonuc = x – 2 * x – 2 / x – 5; // x, 1 ise Sonuc –8 olacaktır.
Burda bizim istediğimiz Sonuc –0.25 olması gerekiyor. Bunu doğru bir şekilde programımıza anlatmamız gerekir bu tür işlemlerde parantezleri doğru kullanmak çok önemlidir. Şimdi doğrusunu yazalım.
Sonuc = ((x – 2) * (x – 2)) / (x – 5); // x, 1 ise Sonuc –0.25 olacaktır.
Böylece istediğimiz sonuca ulaşmış olacağız.
C++ Denetim Deyimleri
Denetim deyimleri koşula bağlı olarak komut satırlarının çalışıp çalışmamasını sağlamak için kullanılır. Ayrıca tekrarlanması istenilen komut satırları içinde denetim deyimler diğer bir ifadeyle koşullu döngüler kullanılır.
Şimdi bu denetim deyimlerini örneklerle inceleyelim.
if Deyimi
En sık kullanılan denetim deyimidir. Yapısı aşağıda gösterildiği gibidir.
if (Koşul1)
{
Komutlar1;
}
else if (Koşul2)
{
Komutlar2;
}
else
{
Komutlar3;
}
Bu komut satırlarında Koşul1 doğruysa diğer bir ifadeyle True değerini geri döndürüyorsa Komutlar1 satırları icra edilir. Koşul1 yanlışsa Koşul2 kontrol edilir. Koşul2 doğru ise Kommutlar2 icra edilir. Koşul2 yanlışsa Komutlar3 kod satırları icra edilir. Burada bilmemiz gereken diğer bir şey {} işaretlerinin kullanımıyla ilgili. {} işaretleri Komutlar1,2,3 kod satırları bir satırdan ibaret ise kullanılmazlar. Bu {} işareti arasında kalan kod satırına o ifadenin gövdesi denir. İfadenin gövdesi tek satırdan oluşuyorsa {} işaretleri kullanılmaz. Şimdi bir örnekle açıklamaya çalışalım.
if (i < 10)
{
n = 10;
k = 20;
}
else
n = 20;
i değişkenin değeri 10’dan küçükse n değişkenine 10, k değişkenine 20 değeri atanır. i değişkenin değeri 10’dan büyükse n değişkenine 20 değeri atanır.
while Deyimi
Koşula bağlı olarak bir veya bir çok komut satırının tekrarlanması için kullanılır.
while (Koşul)
{
Komutlar;
}
Bu denetim deyimi bir koşula bağlı döngü deyimidir. Koşul kontrol edilir doğru ise Komutlar icra edilir. Doğru değilse döngüye hiç girilmeden döngü gövdesinin son satırına gidilir (}) ve bir sonraki satıra geçilir. Koşul doğru ise komutlar icra edilir. Komutlar icra edildikten sonra, döngünün ilk satırına geri gelinir. Koşul tekrar kontrol edilir doğru ise Komutlar icra edilir. Doğru değilse döngüden çıkılır. Bu işlem her seferinde tekrarlanır. Döngüden çıkabilmek için break; komutunun kullanılması veya koşulun yanlış olması gerekir. Bunların hiçbiri yoksa koşul değişmiyorsa sonsuz döngüye girer ve sistem bellek hatası verir. Sonsuz döngüye sokmamak için koşulun değiştiğinden emin olmanız gerekiyor.
do while Deyimi
do while döngüsünün while döngüsünden tek farkı koşulun gövdenin sonunda kontrol edilmesi. Bu döngü yapısında komutlar bir kere mutlaka icra edilir. Bunun sebebi ise koşulun son satırda kontrol edilmesidir. Kullanımı aşağıdaki gibidir.
do
{
Komutlar;
} while (Koşul);
Program döngü gövdesinin baş tarafına geldikten sonra komutları bir kere icra eder. Komutlar bir kere icra edildikten sonra Koşul kontrol edilir. Koşul doğru ise döngünün başına gidilir ve komutlar bir kez daha icra edilir. Yanlış ise bir alt satıra geçilir ve dolayısıyla döngüden çıkılmış olur. Döngüden çıkılması için koşulun yanlış yani false değerini geri döndürmesi gerekir.
for Deyimi
for döngüsü, koşula bağlı olarak aynı kod satırlarının istenilen sayıda tekrarlanmasını sağlar. Kullanımı aşağıdaki gibi yapılır.
for (Sayac; Koşul; Artırım)
{
Komutlar;
}
Sayac değişkeni bir değer tutar, Koşul, Sayac değişkeni ile bir değişken veya sayının ilişkisel ifadesidir. Artırım, Sayac değişkenimizin her döngüde ne kadar artırılacağını belirler. Şimdi bir örnekle çalışmasını anladatalım
for (int i = 0; i < n ; i++)
{
DoFunction(i);
AddNumbers(myArray);
}
Örneğimizde i değişkeni tamsayı tipinde tanımlanıyor. Ve ilk değer olarak 0 alıyor. Döngümüzdeki koşul ifadesine bakacak olursak sayacımız yani i değişkeni bir n değişkeniyle karşılaştırılıyor eğer i n den küçük ise döngüye giriliyor. DoFunction fonksiyonuna i değeri gönderilerek 1 kez çalıştırılıyor. AddNumbers fonksiyonuna myArray dizisi gönderiliyor ve çalıştırılıyor. Döngü sonuna gelindiğinde döngünün ilk satırına tekrar dönülüyor. i değişkenin değeri örneğimizdeki gibi 1 artırılıyor. Koşul ifadesi kontrol ediliyor. i değişkeni n den küçükse döngü içindeki iki komut satırı tekrar icra ediliyor. Bu döngü bu şekilde koşul yanlış olana kadar icra edilir. i değişkeni n den büyük olana kadar komut satırları icra edilecektir. N değeri 10 ise komut satırları 11 kez icra edilecektir.
Bu şekilde bir kod tekrarına neden ihtiyacımız olacaktır diyorsanız örneğin bir veri tabanı dosyasından veri okumamız gerekiyor ve ilk 100 kayıt okuyacağız. Bu işlemi yapabilmek için 100 kere tekrarlanabilecek bir döngü oluşturup her döngüye girişte bir sonraki kayıta geçip okutursanız veri tabanı dosyanızdan verileri birkaç satırla çekebilirsiniz.
switch Deyimi
Bu denetim deyimi, bir değişkenin aldığı değere bağlı olarak bir çok olasılıkta yapılması gereken işlemleri belirleyip bunları ayrı ayrı icra ettirebilmemizi sağlar. Bu deyim if deyimine benzer fakat tek koşul değil birden fazla koşul vardır bu koşullara bağlı olarak birden çok komut satırının icrasını kontrol edebilirsiniz. Kullanımı aşağıdaki gibidir.
switch (Degisken)
{
case Deger1: Komutlar1;
break;
case Deger2:
{
Komutlar2;
}
berak;
default: Action;
break;
}
switch Degisken isimli değişkenimizin değerine bağlı olarak Komutlar1, Komutlar2 ve Komutlar3 satırlarının hangisinin icra edileceğini belirlememize yarar. Degisken Deger1’e eşitse Komutlar1 icra edilir ve break komutunu gördükten sonra switch gövdesinden çıkılır. Degisken Deger2’ye eşitse Komutlar2 icra edilir ve deyimden çıkılır. Degisken hiçbir degere eşit değilse default deyimin altında kalan komut satırları icra edilir. if deyiminin else kısmından sonraki komutları gibidir.
Burada dikkat edilmesi gereken break komutlarının kullanımı, bu komutların kullanılmaması sonucu tüm değerler karşılaştırma işlemine tabi tutulur. default deyimine geldiğinde ise bir karşılaştırma işlemi olmadığından bu kısımın altında kalan komut satırları da icra edilecektir. Bu yüzden break komutunun kullanılmasına dikkat ediniz.
Şimdi bir örnekle açıklamaya çalışalım.
switch (ch)
{
case ‘a’:
{
DoA();
CallHome();
}
break;
case ‘b’: DoB();
break;
case ‘c’: DoC();
break;
default: DoDefault();
break;
}
Bu örnekte ch değişkenin değerine bağlı olarak fonksiyonlara yönlendirme yapılmakta. ch değişkenin değeri a ise DoA ve CallHome fonksiyonları icra edilir. ve çıkılır (break). ch değişkenin değeri b ise DoB fonksiyonu icra edilir ve çıkılır. ch değişkenin değeri c ise DoC fonksiyonu icra edilir ve çıkılır. ch değeri bu durumlardan hiç birine eşit değilse
DoDefault fonksiyonu icra edilir ve çıkılır.
break Komutu
Yukarıdaki örnekte de gösterildiği gibi. break komutu for, while, do while ve switch döngülerinden çıkmak için kullanılır. İç içe yapılmış döngülerin en içteki deyiminden çıkılır. Yani sadece tek döngü terk edilir diğerini terk etmek için ayrı bir break komutu kullanmalısınız.
continue Komutu
continue deyimi while, do while ya da for döngüsünün bulunduğu yerden son satırına gider ve döngünün bir sonraki iterasyonuna başlar. for döngüsünde artırma değeri kadar değer artırıldıktan sonra döngüye devam edilir.
Örneğin,
while (i < 100)
{
i++;
if (i % 10 == 0)
continue;
//Diğer Deyimler
}
i değişkeni döngüye girdiğinde değeri bir artırılır. i değişkeni onun katlarını değer olarak aldığında işlem yapmaması için bir if denetim deyimi ve continue komutlarını kullanıyoruz.
goto Komutu
goto komutu denetimin koşulsuz bir başka satıra gönderilmesini sağlar. Komut satırlarınızın herhangi bir yerinde goto komutunu kullanarak programı istediğiniz komuta gönderebilirsiniz. Yalnız bu işlemi yapabilmek için göndereceğiniz satırlara etiket koymanız gerekmektedir. Kullanımı aşağıdaki gösterilmiştir.
goto label:
//Deyimler
label:
//Deyimler
label:
iostream Aracılığıyla C++ Girdi/Çıktıları
iostream.h dosyası, C++ girdi ve çıktı yapma yolunu tanımlar. Bir iostream, girdi ya da çıktıya veri akımı gibi davranan nesnedir. Çıktıyı çıktı akımına koyarak gönderirseniz ve girdiyi, girdi akımından çekerek elde ederiz.
Cout << “Merhaba, ” << szTo << “ Numara” << NUMARA << “.\n”;
Bu satır, cout olarak adlandırılmış çıkı akımına “Merhaba, C++! Numara 1.” Dizisini yerleştirir. cout nesnesi, ekranınıza ya da ekrandaki bir pencereye denk düşen standart output anlamına gelen standart bir C++ iostream nesnesidir. Aynı zamanda cin olarak bilinen, standart input anlamına gelen ve klavyeye denk düşen bir input stream nesnesi vardır. Visual C++ programında, ekleme işlecini kullanarak diziyi cout’a koymak, eklenmiş dizinin MS – DOS penceresinde görüntülenmesini sağlar.
iostream olanağı, girdi ya da çıktıyı bir dosyaya bağlamak için düzenek içerir. Dosyalara bağlamak ve C++ programlarınızda iostream’in farklı özelliklerini kullanmak hakkında daha fazla bilgi almak için, Help dizininde iostream başlığına bakın ve “iostream Programming” başlığını seçin.
C++’la, iostream nesneleri, Basic’teki Print, Pascal’daki WriteLn, C’deki Printf gibi işlevlerin yerini alır. iostream nesnelerini kullanmak, C++’ta girdi ve çıktıları gerçekleştirmenin normal yoludur.
İşaretçiler ve Başvurular
İşaretçiler
C ve C++ programının en çok kullanılan özelliklerinden biri pointer’dir (İşaretçi). İşaretçi, bellekteki bir yerin adresini içeren bir değişkendir. Bir çok durumda, başka bir değişkenin adresi olur. Aşağıdaki şekil işaretçi ve işaret ettiği hedef (Target) arasındaki ilişkiyi gösterir. C++ programdaki işaretçiler aynı c’deki işaretçiler gibi çalışır.
İşaretçiler konusunda bilmemiz gerekenler aşağıda sıralanmıştır.
· Bir işaretçiyi bildirmek ve ilk kullanıma hazırlamak
· İşaret edilen nesneye erişmek ya da nesnenin değerini değiştirmek
· İşaretçileri en iyi şekilde adlandırmak
· İşaretçiler aracılığıyla ve pointer arithmetic kullanarak dize ve dizinleri beceriyle yönetmek
· İşlev parametrelerinde ve işlev sonuçlarında işaretçileri kullanmak
· İşaretçinin bir çok şeye (değişkenler, dizinler, diziler, yapılar, sınıflar, yapı ya da sınıf üyeleri, null, void*, işlevler ve diğer işaretçiler) işaret edebileceğini anlamak
· İşaretçileri kullanırken dikkat etmek
İşaretçi Temelleri
Aşağıda bulunan ve kısa bir C++ programı olan pointer, işaretçiyi nasıl bildireceğiniz ve ilk kullanıma hazırlayacağınıza ek olarak, işaret edilen nesneye nasıl erişeceğinizi ya da değerini değiştireceğinizi gösterir.
//Pointer.cpp : Konsol uygulaması için giriş noktasını tanımlar.
#include <iostream.h>
int main (int argc, char* argv [])
{
// Bir normal tamsayı değişkeni bildir ve ilk kullanıma hazırla.
int nVar1 = 100;
// nVar1’e bir işaretçi bildir.
int* pInt = &nVar1;
// İşaretçinin nVar1’e işaret ettiğini gösterir
cout << “nVar1 = “ << nVar1 << “ *pInt = “ << *pInt << endl;
// nVar1 adresini pInt’de saklanan değere == olduğunu gösterin.
cout << “&nVar1 = “ << &nVar1 << “ pInt = “ << pInt << endl;
// İşaretçi aracılığıyla nVar1’in değerini öğrenin
int nVar2 = *pInt;
// iŞaretçi aracılığıyla nVar1 in değerini değiştirin
*pInt = 200;
// İşaretçi aracılığıyla düzeltilen değeri gösterin
cout << “nVar2 = ” << nVar2 << “ nVar1 now = “ << nVar1 << endl;
return 0;
}
Pointer programı, int değişkeni olan nVar1’i bildirir. Bir sonraki ifade, nVar1 değişkenin adresini belleğinde tutan bir işaretçi yaratır. Aşağıda, pInt’in nesneye nasıl işaret ettiği gösteriliyor.
int* pInt = &nVar1;
Atama işlecinin sol tarafında, pInt değişkeni, int’e işaretçi olarak bildirilmiştir. İndirection işleci (*), pInt’in int’e işaretçi olduğunu söyler. Atlama işaretçinin sağ tarafında, address işleci (&, ve imi), nVar1 değişkenin adresini edinir. Adres, işaretçinin değerini ilk kullanıma hazırlamak için atanmıştır. İşaretçi, tam olarak budur. Bellekteki bir yerin adresi.
İnt* pInt = &nVar1 işaretçi atamasını iki çıktı ifadesi izler.
cout << “nVar1 = “ << nVar1 << “ *pInt = “ << *pInt << endl;
cout << “&nVar1 = “ << &nVar1 << “ pInt = “ << pInt << endl;
İşaretçiler hakkında iki gerçeği ortaya sererler.
· nVar1 pInt nesnesi aynı değeri işaret eder, dolayısıyla pInt, gerçekten nVar1’er işaret eder.
· nVar1’in adresi ile pInt’te saklanan değer aynıdır, dolayısıyla pInt’in nVar1’e işaretl etmesini sağlayan adres budur.
Daha sonra pointer programı, nVar1’e işaret eden işaretçiyi kullanarak, nVar1’in değerine erişmeyi sağlayan sözdizimini gösterir.
int nVar2 = *pInt;
Burada, * işleci, pointer-derefence işleci olarak kullanılmaktadır. Bu satırı, “nVar’ye, pInt’in işaret ettiği adresteki değer atanmıştır.” Olarak okuyabilirsiniz. Bu durumda, * işeci, “-nin değeri” anlamına gelmektedir. İşleci, dereferencing yaptığınız söylenir, yani hedefte ne olduğunu görmek için işaretçiyi izlersiniz. İkiside * karakteriyle gösterilse de, konumlarıyla izleyen işleci dolaylı işleç den ayırabilirsiniz.
İzleyen işleç, işaretçinin adını izler ama dolaylı işleç gibi değişken bildiriminin bir parçası değildir. Bir sonraki sayfadaki iki ayrı satırda bu işleçler gösterilmiştir.
int* pInt = &nVar1; // Dolaylı işleç *
int nVar2 = *pInt; // İzleyen işleç *
İşaretçi aracılığıyla nVar1’de bir değere erişebilmenin yanı sıra, işaretçi aracılığıyla o değeri de değiştirebilirsiniz.
*pInt = 200;
Bu sefer izleyen işleç, atama ifadesinin sol tarafında görülür. Buradaki anlamı “pInt tarafından işaret edilen adreste 200 değerini sakla” olmaktadır.
Pointer programındaki son çıktı ifadesi nVar2’nin yeni atama değerini ve nVar1’in yeni değerini gösterir. nVar1’in başlangıç değeri 100’dü şimdi 200 olarak ayarlandı.
İşaretçi ve Diziler
Dizilerle önceden karşılaştınız. C ve C++ programında dizilerin, işaretçilerle ilginç ve yararlı bir ilişkisi vardır. Her iki dilde de, array name, dizinin ilk öğesine işaretçidir. Bunun anlamı, dizinin öğelerini “gözden geçirmek” (döngülemek, yinelemek, üzerinden geçmek) için, işaretçiler başka bir seçenek sağlarlar. Aşağıdaki Array Programı pointer arithmetic kullanarak diziyi gözden geçirmeyi göstermektedir.
#include <iostream.h>
int main (int argc, char* argv [])
{
cout << “—-1. Using Array Notation—–\n”;
int arInt[] = {6, 5, 4, 3, 2};
for (int i = 0 ; i < 5 ; i++)
cout << “arInt[” << i << “] = “ << arInt[i] << endl;
cout << “—–2. Using Pointer Arithmetic—–\n”;
int* pArray = arInt;
for (int j = 0 ; j < 5 ; j++)
{
cout << “arInt[“ << j << “] = “ << *pArray++ << endl;
}
return 0;
}
Array programıın iki bölümü vardır. İlk bölümü dizinin öğelerini gözden geçirmek için for döngüsünde normal dizi simgelemesi kullanır. C++ programının anahtar parçası, çıktı akımının ortasındaki bu diziye erişme simgelemesidir.
ArInt[i]
Kod dizinin, i değerindeki öğesinde saklayan değeri geri almak için, diziye array subscript işlecini ([]) uygulanır. Burada değer çıktı akımının içine koyulur.
Array programının ikinci bölümü iki değişikliği ortaya çıkarır. İlk olarak, int değişkenine pArray adında bir işaretçi bildirilir ve yalnızca dizi adıyla ilk kullanıma hazırlanır. Dizi adının işaretçi olduğunu unutmayın. İlk kullanıma hazırlamadan sonra, pArray dizinin ilk öğesine işaret eder. Sonra, çıkı akımında dizi erişim simgelemesi, tuhaf görünümlü bir kodla değiştirilir.
*pArray++;
pArray’e iki C++ işleci uygulanır. İzleyen işleç, işaretçi adından önce gelir. Dolayısıyla yaptığımız, pArray’ın ilk öğesinin geçerli konumundaki değeri yeniden almaktır. İşaretçi adının arkasında arkaya konulan ek olan artırma işleci (++) vardır. Bundan sonra yaptığımız diğer şey işaretçiyi artırmak. Buna genelde işaretçi aritmetiği denir. İşaretçide saklanan adres 1 ekleyerek, dizide bir sonraki öğeye işaret etmesi için işaretçinin yerini değiştiriyoruz.
İşaretçi ve Dizeler
C deki dizeler gibi, C++ programındaki dizeler de karakter dizileridir. Dize değişkeni adı, diğer tüm dizilerin adı olduğu gibi, işaretçidir, String pogramı, char* değişkeni üzerinde işaretçi aritmetiği kullanmayı gösterir.
#include <iostream.h>
int main (int argc, char* argv [])
{
cout << “—Using Pointer Notation on an Array–\n”;
char arStr1[] = “Programming”;
char* pStr1 = arStr1;
cout << arStr1 << endl; // ilk tüm diziyi yazar
while (*pStr1)
cout << “*pStr1 =” << *pStr1++ << endl;
return 0;
}
String Programı, dizeyi taramak ve sırasıyla her bir karakteri yazdırmak için bir işaretçi kullanılır. Dizenin adının (arStr1) yalnızca dizenin ilk karakterine işaretçi olduğunu hatırlayın. Dizeyi gözden geçirmek için, bu sefer char*’a olmak üzere ikinci bir işaretçi bildiririz ve ilk kullanıma dize adıyla hazırlarız. İkinci işaretçiyi gözden geçirme amaçlı kullanmak, dize adını hala birinci karaktere işaret eder bir halde bırakır. Bunun yerine özgün dize işaretçinin (arStr1) yerini değiştirmek ise, dize adını gözden geçirme sonunda konumsuz bırakır. Dolayısıyla, diziyi yardımcı işaretçiyle gözden geçirmek çok daha güvenlidir.
İşlev Parametreleri ve İşlev Sonuçları Olarak İşaretçiler
Değer Aracılığıyla Geçiş
Parametreyi işleve geçirmenin varsayılan yoluna passing by value denir. Değer aracılığıyla geçiş yaptığınızda, işlev, işlev çağrısında sağladığınız verinin gerçeğini almaz. Bunun yerine, verinin kopyası yapılır ve işlev bu kopya üzerinde çalışır. İşlev kopyayı istediği gibi değiştirebilir ve özgün veri değişmeden kalır. Yalnızca değer aracılığıyla geçişin kopya geçişi yaptığını hatırlayın.
İşlev sonucunu varsayılan yolla döndürmek, onu değer aracılığıyla döndürmektir. Yine bir kopya yapılır ve işlevden çıkıp dışarıdaki dünyaya giren bu kopyadır.
Adres Aracılığıyla Geçiş
İşlevin üzerinde çalışmasını istediğiniz büyük bir veri parçanız olduğunu varsayın. Bu durumda, işleve geçirdiğiniz verinin işlev tarafından değiştirmesini bilerek istiyorsunuz. Ancak varsayılan yol işlevin yalnızca kopya üzerinde çalışmasına izin veren değer aracılığıyla geçiştir.
Tabii ki çözüm, veriye işaretçi geçişi yapmak, yani pass by address yolunu kullanmaktır. Bu yolla verilerin kopyası kullanılmaz. İşlev, işaretçiyi nerede olduğuna bakmaksızın özgün veriyi değiştirmek için kullanabilir.
Adres aracılığıyla geçiş, işlev sonuçlarını vermesi için de aynı biçimde çalışır. Yalnız burada asıl güdü verimliliktir. Döndürülecek büyük bir veri kopyası yoktur. İşlevi döndürmek için yazılacak bir kod aşağıdakine benzer.
Thing MyFunction()
{
// Bir Thing yaratmak için birşeyler yapın
return &Thing;
}
İşaretçileri geçirmenin ve döndürmenin başka bir yararı da, birden çok sonucu döndürmenize olanak sağlamalıdır. Ek sonuçlar döndürmek için işaretçi tipi parametreler kullanabilirsiniz. Aşağıda şematik olarak gösterilmiştir.
Return Return
int AFunction( int nParam1, int* pnParam2)
{
*pnParam2 = 3;
return 4;
}
Bir Const İşaretçisi Geçirmek
İşaretçiler hakkında bir başka şeye daha dikkat edin. Değer aracılığı yerine adres aracılığıyla geçiş yapmanızın asıl nedeni ön işlemleri kopyalamaktan sakınmak olduğunu varsayın ve verinin kendisinin işlev içinde değiştirilmesini istiyorsunuz. Bu durumda, aşağıda gösterildiği gibi parametreyi const değiştiricisiyle bildirebilirsiniz.
Void MyFunctuion (const Thing* pThing)
const işaretçisini bu şekilde kullanmak, derleyiciyi isteklerinizi yerine getirmesi için zorlar. pThing aracılığıyla Thing’e işaret edilen, işlevde değiştirilemez. İşlevin veriyi değiştirmesini amaçlamıyorsanız, const parametreleri geçirmek iyi bir alışkanlıktır.
Başvurular
C++ yeni bir değişken türü tanıtır: reference (Başvuru) değişkeni. Refe1 programı basit bir örnek verir.
#include <iostream.h>
int main (int argc, char* argv [])
{
// Bir int değişkeni tanımlayın ve ona başvurun
int myInt = 3;
int& rMyRef = myInt;
// rMyRef’in mInt’e başvurduğunu gösterin
cout << rMyRef << endl; // Çıktı 3’tür
// myInt’i değiştirerek rMyRef’i değiştirin.
MyInt += 1; // Şimdi 4’e eşittir
Cout << rMyRef << endl; // Çıktı 4’tür
// rMyRef aracılığıyla myInt’i değiştirin
rMyRef += 1;
// Bir sonraki satır “rMyRef = 5 myInt=5” çıkarır
cout << “rMyRef = ” << rMyRef << “ myInt = “ << myInt << endl;
return 0;
}
Bir başvuru, diğer bir değişken için alias (arma), yani aynı nesne için farklı bir addır. Başvuru, işaretçi gibi kendi başına ayrı bir nesne değildir. O, yalnızca bir addır. Yukarıdaki örnekte, rMyRef’in myInt’e işaret (refer) ettiği söylenir. Yani myInt için bir armadır. myInt’e doğrudan yapabileceğiniz herhangi bir şeyi rMyRef başvurusu ile de yapalirsiniz.
İşaretçiye benzese ve biraz onun gibi davransa da belirli bir değişkene başvurabilmek için, başvurunun ilk kullanıma hazırlanması gerekir. Bundan sonra, başvurması için farklı bir değişkene atanamaz. Unutmayın: bir başvuru varolan (başvuru süresince varlığını sürdürecek) bir nesneye başvurmalıdır.
Refer1 programında gösterildiği gibi başvuruları kullanabilirsiniz. Ancak işlev parametre ve sonuçları olarak kullanımları en yaralı kullanımlarıdır. Söz ettiğimiz birkaç kurala uyduğunuz sürece verimliliğinizi yükseltebilirler.
Başvuru Aracılığıyla Geçiş
Diğer iki parametre geçişi düzeneklerini işledik:
· Değer aracılığıyla geçiş, kopya geçirilir ve özgün veri, kopya aracılığıyla değiştirilemiyor.
· Adres aracılığıyla geçiş, işaretçi geçirilir ve bu işaretçi aracılığıyla (işaretçi parametresi const olmadığı sürece) özgün veri değiştirilebilir.
C++ programındaki üçüncü ve son parametre geçişi düzeneğini pass by reference denilir. Resmi parametre, başvuru tipini belirtir. Bu örnekte başvuru tipi BigObject& olarak gösterilmektedir.
Void MyFunction(BigObject& rBo);
Ve geçirdiğiniz başvuru değişkeni olmayan (nesneye işaretçi değil de, nesnenin kendisi) gerçek parametre, başvuru parametresini ilk kullanıma hazırlar:
BigObject myBo; // myBo, yığında gerçekten nesne olarak vardır
MyFunction(myBo); // myBo başvuru parametresini sıfırlamak için kullanıldı
MyFunction, özgün nesne olan myBo’yu ona yapılan başvuru aracılığıyla (parametre bildirisinin önüne const anahtar sözcüğünü koymadığımız sürece) değiştirebilir. Bir sonraki program Refer2, başvuru parametresinin başvurduğu nesnesinin nasıl değiştirileceğini gösterir.
#include <iostream.h>
struct BigObject
{
int Var1;
double arDd1[2000]; // 2.000 kesirli sayı için yer ayırır
};
void MyFunction (BigObject& bo);
int main (int argc, char* argv [])
{
Bigobject myBo;
myBo.Var1 = 0;
cout << “Before MyFunction call, myBo.Var1 = ” << myBo.Var1 << endl;
MyFunction(myBo);
cout << “After MyFunction call, myBo.Var1 now = “ << myBo.Var1 << endl;
return 0;
}
void MyFunction (BigObject& bo)
{
cout << “Entering My Function, bo.Var1 = ” << bo.Var1 << endl;
bo.Var1 = 100;
}
Refer2 programı, BigObject adında bir struct tipi bildirir. BigObject, iki öğe değişkeni içerir: bir int ve geniş bir doubles dizisi, Refer2, main’deki yığında myBo adında bir BigObject yaratır ve int öğe değişkeni olan, Var1’i ilk kullanıma hazırlar. Daha sonra main, MyFunction’ı çağırıp başvuru aracılığıyla BigObject’e geçirir. İşlev sırasında & ya da farklı süslemeler yapmadan nesnenin adını geçirdiğimize dikkat edin.
Üst Bilgi ve Gerçekleştirme Dosyaları
Şimdiye kadar çoğu yerde, örnek programdaki herşeyi (bildiri ve tanımları) tek bir .cpp dosyası olan C++ implementation dosyası içine koyduk. Ancak, c++ programında program yazmanın genel yolu, bildirileri üst bilgi (header) dosyası (.h uzantılı) ve tanımları .cpp dosyası içine koymaktır o zaman .cpp dosyası .h dosyasını, aşağıda gösterildiği gibi içerir.
#include “myHdr.h”
C++ programındaki üst bilgi ve gerçekleştirme dosyaları aynı C’deki gibidir. Kodu üst bilgi dosyası ve gerçekleştirme dosyası olarak ayıran Refer3 programının farklı bir sürümünü, Refer4 programını yaratalım. Gerçekleştirmek (.cpp) dosyası, üst bilgiyi içermelidir. Projeyi Refer4 olarak adlandırıp sihirbazla bu dosyaları yaratın.
#include <iostream.h>
#include “Refer4.h”
int main (int argc, char* argv [])
{
Object& rMyObj = MyFunction();
cout << “rMyObj.a = ” << rMyObj.a << endl;
delete &rMyObj; //Başvurulan nesneyi silin
return 0;
}
Object& MyFunction()
{
Object* o = new Object; // Kümede nesne yaratın
o -> a = 20; // Değerini ayarlayın
o -> b= 25;
return *o; // Nesnenin kendisini döndürün
}
Üst bilgi dosyası olan Refer4.h’i yaratın, aşağıdaki kodu ekleyin ve projeyi ona ekleyin. Üst bilgi dosyasını yaratmak için, File menüsünden New komutunu kullanın. New iletişim kutusunda Files sekmesini tıklayın C/C++ Header File’ı tıklayın ve File Name kutusunda dosyaya bir ad verin (Refer4.h). Add To Project seçeneğinin işaretli olduğundan ve proje adının Refer4 olduğundan emin olun.Üst bilgi dosyasını Refer4 projesinin bir parçası olarak yaratmak için OK düğmesini tıklayın.
struct BigObject
{
int a;
int b;
};
object MyFunction();
Kodu neden böyle bölüyoruz? Refer4.h deki Object yapısı gibi çok yararlı bir veri tipi geliştirdiğimi varsayalım. Bu tipi diğer programlarda yeniden kullanmak isteyebilirim. Program A için tip bildirisi .cpp dosyasına katılmışsa, B programında onu kullanabilmek için, onun bir kopyasını yapıp B programının .cpp dosyasına yapıştırarak kopyalamalıyım. Ancak, tip bildirileri, işlev bildirileri, değişmezler ve diğer yeniden kullanılabilen öğeler bir ya da daha fazla üst bilgi dosyası içindedir ve herhangi bir program, yalnızca üst bilgi dosyalarını içererek onları yeniden kullanabilir.
Nisan 6, 2009 1:28 pm
İşime Yaradı Ellerine Sağlık :=)
Googleden Bunu Yazıp Sen Çıktın “visual c++ dersleri”