C++ Nesne

Nesneye yönelik programlama (NYP) ile geliştirilen uygulamalarda program içinde, veriler ile verilere işlem yapacak olan fonksiyonlar (metodlar) sınıf (class) adı verilen yapılar içinde tanımlandıktan sonra bu sınıf türünden bir değişken (nesne) oluşturularak, bu nesne yoluyla sınıf içinde yer alan tüm değişken ve fonksiyonlara erişim sağlanır.

Bir nesne oluşturmadan önce, class anahtar kelimesini kullanarak nesnenin tüm değişken ve fonksiyonlarını gösteren genel yapısını tanımlamamız gerekir.

Sınıflar class anahtar kelimesi ile oluşturulur. Bir sınıf oluşturulduğunda, sınıf içindeki verilere yine sınıf içindeki fonksiyonların işlem yapmasını sağlayan yeni bir veri türü tanımlanmış olur.

Sınıf adı verilen bu yeni veri türü oluşturulduktan sonra, bu sınıfa ait nesne bildirimi yapılır. Bu işlem, int bir veri türünden değişken tanımlamaya benzer.

Nesne (Object) bildirimi

Nesne bildirimi 2 farklı yöntemle yapılabilir:

  1. Nesne bildirimi sınıf bildirimi ile birlikte yapılır.

  2. Sınıf bildirimi yapıldıktan sonra, sınıf adını kullanarak nesne bildirimi yapılır.

Sınıf bildirimi ile birlikte nesne bildirimi

Devamı...

C++ Sanal (virtual) fonksiyonlar

Sanal fonksiyonlar bir ana sınıf içinde bildirimi yapıldıktan sonra türetilen sınıf içinde tekrar tanımlanır. Sanal fonksiyon bildirimi için kullanılan genel yapı aşağıda gösterilmektedir:

Devamı...

C++ Fonksiyon şablonları

Bir fonksiyon şablonu, çeşitli veri türlerine uygulanacak genel bir işlem grubunu tanımlar. Fonksiyonun üzerinde çalışacağı veri türü fonksiyona bir parametre olarak aktarılır. Fonksiyon şablonu ile, geniş bir veri yelpazesine tek bir genel kod yapısı uygulanabilir. Farklı veri türlerine aynı kodlarla işlem yapılması gerektiğinde fonksiyon şablonlarını kullanılması büyük kolaylık sağlar.

Bir fonksiyon şablonu template ve typename anahtar kelimeleri ile oluşturulur. Fonksiyon şablonu bildirimi için kullanılan genel yapı aşağıda gösterilmektedir:

Devamı...

C++ Fonksiyonları yeniden tanımlama (Overriding)

Nesneye yönelik programlamada, kalıtım özelliğini kullanarak, bir ana sınıftan sınıflar türetebiliriz. Bir ana sınıftan bir sınıf türetildiğinde, ana sınıfta yer alan tüm değişken ve fonksiyonlar türetilen sınıf tarafından kullanılabileceği gibi, türetilen sınıf içinde de yeni değişken ve fonksiyonlar tanımlanabilir.

Eğer ihtiyaç duyulursa, ana sınıftan devralınan fonksiyon adları ile aynı ada sahip fonksiyonlar tanımlanarak, ana sınıftan devralınan fonksiyonlar geçersiz hale getirilir ve aynı isim altında farklı kodlar yazılır. Bu durumda, aynı fonksiyon hem ana sınıfta hem de türetilmiş sınıfta tanımlanmış olur. Bu fonksiyon türetilmiş sınıf nesnesi ile çağrıldığında, türetilmiş sınıfın fonksiyonu çağrılır. Bu özelliğe, Fonksiyonu Yeniden Tanımlama adı verilir. Türetilmiş sınıftaki fonksiyon, ana sınıftaki fonksiyonun yerini alır.

Fonksiyonu yeniden tanımlama işleminin yapılabilmesi için, bir ana sınıftan bir sınıf türetilmesine, kalıtım özelliğinin kullanılmasına, ihtiyaç vardır.

Fonksiyonları yeniden tanımlama işlemi, bir ana sınıf ve ana sınıftan türetilmiş olan bir veya daha fazla türetilmiş sınıf içinde yapılır. Bu işlem iki farklı yöntemle uygulanabilir:

  • Sınıf fonksiyonlarını doğrudan yeniden tanımlama
  • Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama

İki yöntemin kullanılması arasındaki fark, doğrudan yeniden tanımlama yönteminde, ana sınıf işaretçisine türetilen sınıf nesnesinin adresi atandığında, ana sınıf işaretçisi ana sınıf içindeki fonksiyonlara erişim sağlarken, sanal yöntemle yeniden tanımlama yönteminde, türetilen sınıf içindeki fonksiyonlara erişim sağlamaktadır.

Sınıf fonksiyonlarını doğrudan yeniden tanımlama

Sınıf üye fonksiyonlarını yeniden tanımlama işlemi yaparken, ana sınıf içinde tanımlanan bir fonksiyon ile aynı isme sahip bir fonksiyon ana sınıftan türetilmiş bir sınıf içinde tanımlanır ve kod içeriği yeniden yazılır. Bu durumda, ana sınıf ve bu sınıf içinde aynı isme sahip iki fonksiyon oluşturulur. Bu fonksiyonlara ana sınıf ve türetilmiş sınıftan oluşturulan işaretçi ve nesneler yoluyla yapılan erişimler aşağıda gösterilen esaslara göre yapılmaktadır:

  1. Türetilen sınıf içinde yeniden tanımlanan fonksiyon ile aynı isme sahip ana sınıf içindeki fonksiyona ana sınıf nesnesi ile erişim sağlanır.
  2. Türetilen sınıf içinde yeniden tanımlanan fonksiyona türetilen sınıf nesnesi ile erişim erişim sağlanır.
  3. Türetilen sınıf içinde yeniden tanımlanan ana sınıf fonksiyonlarına türetilen sınıf nesnesi ile erişim sağlamak aşağıdaki ifadeyi kullanabiliriz: türetilen-sınıf-nesnesi.ana-sınıf-adı::fonksiyon-adı
  4. Ana sınıf işaretçisine türetilen sınıf nesnesinin adresini atandığında, bu işaretçi yoluyla türetilen sınıf içinde yeniden tanımlanan fonksiyon ile aynı isme sahip ana sınıf içindeki fonksiyona eriğşim sağlanır.
  5. Türetilen sınıf içinde yeniden tanımlanan fonksiyon içinden aşağıdaki ifade kullanıldığında, aynı isme sahip ana sınıf içindeki fonksiyona erişim sağlanır. ana-sınıf-adı::fonksiyon-adı

Şimdi, bu uygulamaları bir örnek üzerinde incelemeye çalışalım:

Örnek

Devamı...

C++ Fonksiyon çoklu görev (Overloading)

Çok biçimlilik sözlük anlamı olarak birden fazla şekilde varlık gösterebilen nesne ya da kavramları ifade etmektedir. Fonksiyonlar açısından çok biçimlilik aynı isme sahip bir fonksiyonun çok amaçlı kullanılması için, farklı sayıda ve veri türündeki parametrelerle tanımlanması olarak ifade edilebilir.

Fonksiyonlarda çoklu görev tanımlama (overloading) işlemi

C++’da, fonksiyonlarda çoklu görev tanımlama işlemi yapılırken çok biçimlilik özelliği kullanılır. Birden fazla fonksiyon, farklı veri türündeki ve/veya farklı sayıda parametrelerle bildirimleri yapıldığında, aynı adı kullanır ve program içinden farklı parametreler ve aynı ad ile çağrılırlarsa, fonksiyon çoklu görev tanımlama işlemi gerçekleştirilmiş olur. Böylece, program içinde tek bir isim kullanarak birden fazla fonksiyona erişim sağlanabilir.

Burada kullanılan çoklu görev tanımlama ifadesi birden fazla fonksiyonun aynı isim ile çağrılarak kullanılacağını gösterir.

Böyle bir fonksiyon çağırıldığında, çağrı fonksiyon çağrısında kullanılan parametre sayısı ve tiplerine uygun olarak ilgili fonksiyona yönlendirilir. Bu özelliği bir örnek üzerinde incelemeye çalışalım:

Örnek

Devamı...

C++ Değişken şablonları (C++ 14)

C++14 sürümü ile birlikte değişken şablonları oluşturma olanağı sağlandı. Bir değişken şablonu template anahtar kelimesi ile oluşturulur. Değişken şablonu bildirimi için kullanılan genel yapı aşağıda gösterilmektedir:

Devamı...

C++ Sınıf

Nesneye yönelik programlama (NYP) çalışma sistemi sınıflar içinde yer alan iki temel kavram üzerinde şekillenir:

  1. Değişkenler (veriler): NYP ile geliştirilen uygulamalarda ihtiyaç duyulan farklı türden değişkenler sınıf içinde tanımlanır.

  2. Değişkenlere işlem yapan fonksiyonlar (metodlar): NYP ile geliştirilen uygulamalarda sınıf içinde tanımlanan değişkenlere işlem yapmak üzere fonksiyonlar içinde kodlar tanımlanır.

NYP ile geliştirilen uygulamalarda program içinde, veriler ile verilere işlem yapacak olan fonksiyonlar (metodlar) sınıf (class) adı verilen yapıların içinde tanımlanır. Sınıf tanımlandıktan sonra bu sınıf türünden bir değişken (nesne) oluşturularak, bu nesne yoluyla sınıf içinde yer alan tüm değişken ve fonksiyonlara erişim sağlanır.

Sınıf (Class) bildirimi

Bir nesne oluşturmadan önce, class anahtar kelimesini kullanarak nesnenin tüm özellik (değişkenler) ve davranışlarını (fonksiyonlar) gösteren genel yapısını tanımlamamız gerekir.

Sınıflar class anahtar kelimesi ile oluşturulur. Bir sınıf oluşturulduğunda, sınıf içindeki değişkenlere yine sınıf içindeki fonksiyonların işlem yapmasını sağlayan yeni bir veri türü tanımlanmış olur.

Sınıf adı verilen bu yeni veri türü oluşturulduktan sonra, bu sınıfa ait nesne bildirimi yapılır. Bu işlem, int bir veri türünden değişken tanımlamaya benzer.

Bir sınıf bildiriminin genel yapısı aşağıda gösterilmektedir:

Devamı...

C++ Çok biçimlilik

Çok biçimlilik sözlük anlamı olarak birden fazla şekilde varlık gösterebilen nesne ya da kavramları ifade etmektedir. Nesneye yönelik programlamada ise, çok biçimlilik fonksiyon ve işlemcilerin birden fazla görev için kullanılmaları ile kalıtım ve sanal fonksiyonların kullanılmasını içerir.

C++’da, iki tür çok biçimlilik özelliği vardır:

  • Derleme zamanı çok biçimliliği: Statik veya erken bağlama olarak bilinir.
  • Çalışma zamanı çok biçimliliği: Dinamik veya geç bağlama olarak bilinir.

C++’da, çok biçimlilik kavramını aşağıda gösterilen dört farklı yöntemle uygulayabiliriz:

  • Fonksiyonlara çoklu görev tanımlama (Overloading) işlemi
  • İşlemcilere çoklu görev tanımlama (Overloading) işlemi
  • Sınıf fonksiyonlarını doğrudan yeniden tanımlama (Overriding)
  • Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama (Overriding)

Fonksiyonlara çoklu görev tanımlama (Overloading) işlemi

C++’da, fonksiyon çoklu görev tanımlama işlemi yapılırken çok biçimlilik özelliği kullanılır. Birden fazla fonksiyon, farklı veri türündeki ve/veya farklı sayıda parametrelerle bildirimleri yapıldığında, aynı adı kullanır ve program içinden farklı parametreler ve aynı ad ile çağrılırlarsa, fonksiyon çoklu görev tanımlama işlemi gerçekleştirilmiş olur. Böylece, program içinde tek bir isim kullanarak birden fazla fonksiyona erişim sağlanabilir. Burada kullanılan çoklu görev tanımlama ifadesi birden fazla fonksiyonun aynı isim ile çağrılarak kullanılmasını gösterir. Böyle bir fonksiyon çağırıldığında, çağrı fonksiyon çağrısında kullanılan parametre sayısı ve tiplerine uygun olarak ilgili fonksiyona yönlendirilir. Fonksiyon çoklu görev tanımlama işlemi için bir ana sınıftan bir sınıf türetilmesine ihtiyaç yoktur.

Fonksiyon çoklu görev tanımlama işlemini normal fonksiyonlara ve sınıflar içinde yer alan üye fonksiyonlara uyglayabiliriz. Bu özelliği bir örnek üzerinde incelemeye çalışalım:

Örnek

Devamı...

C++ Kalıtım

Kalıtım nesneye yönelik programlamanın en önemli özelliklerinden biridir. Kalıtım bir nesneden türetilen bir nesnenin türetildiği nesnenin tüm özelliklerine sahip olmasıdır.

Kalıtım, nesneye yönelik programlamada mevcut bir sınıf içinde bulunan veri ve metotların bu sınıftan türetilen alt sınıflar içinde kullanılması olarak tanımlanabilir.

Kendisinden türetme yapılan sınıf ana, ebeveyn veya süper sınıf olarak, türetilen sınıflar ise çocuk, alt veya uzantı sınıf olarak isimlendirilir.

Bir ana sınıftan bir sınıf türetildiğinde, ana sınıfta yer alan tüm veri ve metotlar türetilen sınıf tarafından kullanılabileceği gibi, türetilen sınıf içinde de yeni veri ve metotlar tanımlanabilir. Eğer ihtiyaç duyulursa, ana sınıftan devralınan metotlar yeniden tanımlanır (overriding) ve aynı isim altında farklı kodlar yazılır.

Ana sınıftan bir alt sınıf türeterek, ana sınıfta yer alan veri ve metotların devralınması, devralınan metotlar için yeniden kod yazmaya gerek duymadan, ana sınıf içinde yer alan veri ve metotları kullanmaya olanak sağlar.

Öncelikle bir ana sınıf tanımlaması yapılmalıdır. Ana sınıf tanımlaması yapılırken, bu sınıftan üretilecek olan sınıfların ortak olarak sahip olacağı ve birlikte kullanacağı özellikleri gösteren değişkenlerin tamamının bildirimi ana sınıf içinde yapılmalıdır. Ana sınıftan türetilen alt sınıfların sadece kendileri tarafından kullanılacak özellikleri gösteren değişkenlerin bildirimi ise türetilen alt sınıfların içinde yapılmalıdır.

Ana sınıftan türetilen alt sınıflardan da alt sınıflar türetilerek çoklu kalıtım özelliği kullanılabilir.

Ana sınıf erişim kontrolü

Bir sınıf ana sınıf olarak kabul edilerek bu sınıftan bir sınıf türetildiğinde, ana sınıf içinde yer alan tüm elemanlar (değişken ve fonksiyonlar) türetilen sınıfın üyesi haline gelir. C++ dilinde, bu işlemi gerçekleştirmek için aşağıda gösterilen genel yapı kullanılır:

Devamı...

C++ Önişlemci direktifleri

Derleme işleminin ilk safhasında, önişlemci derleyiciye bazı direktifler ulaştırır. Derleyici tarafından bazı özel işlemlerin yapılmasını sağlayan bu direktiflere Önişlemci Direktifleri adı verilir. Şimdi, önişlemci direktiflerini sıra ile incelemeye çalışalım:

#define önişlemci direktifi

#define önişlemci direktifi, programlarımızın herhangi bir işlem satırında kullanılmak üzere, istediğimiz ifadelerin kısa bir isim altında tanımlamamızı sağlar. #define önişlemci direktifinin genel yapısı aşağıda gösterilmektedir:

Devamı...

C++ Nesneye yönelik programlama

Bilgisayar kullanımı ile birlikte programlama her geçen gün farklı boyutlarda gelişmeye devam etmektedir. Başlangıçta, yazılım geliştirme açısından zaman ve çalışma gerektiren direk makine kodlarının kullanımı ile hayata geçirilen bilgisayar programları için, ihtiyaçların artması ve daha kısa zamanda sonuca ulaşma ihtiyacı ile birlikte daha farklı yöntemlerle geliştirilmeye başlanmıştır.

Önceleri Assembly dilinin daha sonra da FORTRAN gibi yüksek seviyeli programlama dillerinin icadı ile programların daha kolay bir şekilde geliştirilmesine olanak sağlanmıştır.

Programların istenilen özellikleri karşılamasında yaşanan sıkıntılarla birlikte yapısal programlama adı verilen bir kavram geliştirilmiştir. C ve Pascal gibi programlama dilleri ile gelen bu özellikle, fonksiyon ve kod bloğu gibi toplu kod tanımlamaları ve bu kod bloklarının aynı isimlerle defalarca çağrılabilmesi daha karışık ve büyük çaplı kodların daha okunur ve açık bir şekilde düzenlenebilmesi sağlanmıştır.

Programlama yaparken daha büyük kolaylıklara ihtiyaç duyulunca, belirli verilerin bu verilerle ilgili kodlarla ilişkilendirilmesi temel prensibine bağlı olan Nesneye Yönelik Programlama (Object Oriented Programming) kavramı geliştirilmiştir. Bu kavram ile birlikte, verilere işlem yapacak kodların metod adı verilen fonksiyonlar içinde yazılması ve verilerle birlikte tek bir yapı içinde tanımlanması ve tüm işlem yetkilerinin bu yapı içinde belirlenmesi esas alınmıştır.

Nesneye yönelik programlama, Kapsülleme (Encapsulation), Kalıtım (Inheritance) ve Çok biçimlilik (Polymorphism) adı verilen dört temel kavramı esas alarak çalışır. Bu esasları gerçekleştirmek için de Sınıf (Class) ve Nesne (Object) kavramlarını kullanır.

Soyutlama (Abstraction)

Soyutlama, kullanıcıya yalnızca ilgili ayrıntıların gösterilmesi ve ilgisiz ayrıntıların gizlenmesi olarak ifade edilebilir. C++’da kullanılan temel soyutlama sistemleri sınıflar, sınıflar yoluyla yapılan kalıtım ve şablonlardır.

Soyutlama, genellikle veri soyutlama amacıyla kullanılır. Veri soyutlama kullanımı için, içinde en az bir adet saf sanal fonksiyon bulunan soyut (abstract) bir sınıf oluşturulur. Bir sınıf içinde en az bir adet saf sanal fonksiyon tanımlanırsa, bu sınıf soyut (abstract) sınıf haline gelir. Bu soyut sınıf kendisinden türetilen alt sınıfların ortak değişkenlerini ve fonksiyonlarını içerir. Soyut bir sınıftan türetilen tüm sınıflarda sanal fonksiyon bildirimi yeniden yapılmalıdır. Eğer yapılmazsa, türetilen sınıflarda soyut sınıf olarak kabul edilir. Soyut sınıflar saf sanal fonksiyon dışında normal fonksiyonlar ve değişkenler içerebilir.

Soyut sınıfları kullanılarak geliştirilen yazılımlarda değişiklik yapmak gerektiğinde, soyut sınıflarda yer alan ve türetilen sınıflar tarafından kullanılan private erişim özelliğine değişkenlerin değiştirilmesi yeterli olmaktadır. Soyut sınıflarda bildirimi yapılan private değişkenler veri güvenliğini artırır ve program kodlarının daha pratik yazılmasını sağlar.

Kapsülleme (Encapsulation)

Kapsülleme, programda bir sınıf içinde tanımlanan verileri ve yine aynı sınıf içinde tanımlanan ve bu verilere erişim sağlayarak kullanan metod veya fonksiyon adı verilen sistemi ifade eder. Bu sistemle, sınıf içinde ye alan veriler ve bu verilere erişim sağlayan kodlar bir bütünlük içinde korunarak, dışarıdan erişimi kısıtlanır. Böylece, program kendi içinde bir kod ve veri güvenliği sağlar. Bu sistemde, kod ve veri tek bir isim altında tanımlanarak, oluşturulan bir sınıf içindeki veri ve kodlar (metodlar) korunur.

Kapsülleme verileri ve bu verileri kullanan ya da değiştiren program kodlarını birbirine bağlayarak dışarıdan yapılabilecek müdahalelere karşı koruyan bir sistemdir. Nesneye yönelik programlamada, bir sınıf tanımlaması altında kod ve veri bu şekilde koruma altına alındığında bir nesne oluşturulmuş olur. Nesne kapsamındaki veri ve verilere işlem yapan kodlar, sadece içinde tanımlı olduğu nesne tarafından (private) veya dışarıdan erişilecek şekilde (public) tanımlanabilir. Nesne içinde private olarak tanımlanmış özel kod ve verilere sadece nesne içinde yer alan diğer kodlar tarafından erişilebilir. Nesne dışında yer alan kodlar nesneye ve özel verilere erişemezler.

Nesne içinde public olarak tanımlanan kod ve veriler tüm erişimlere açık olduğundan, programın nesne dışında kalan kodları bu kod ve verilere erişim sağlar. Nesne içinde programdaki tüm kodların erişimine açık veri ve kodlar açık olarak tanımlanır. Tüm erişimlere açık olan nesne elemanları, nesneye özel elemanlara erişim için kullanılır. Bu durumda, nesne dışındaki kodlar nesne içindeki tüm erişimlere açık kodlar yoluyla nesne içindeki nesneye özel veri ve kodlara da erişebilirler.

Kalıtım (Inheritance)

Kalıtım nesneye yönelik programlamanın en önemli özelliklerinden biridir. Kalıtım bir nesneden türetilen bir nesnenin türetildiği nesnenin tüm özelliklerine sahip olmasıdır.

Kalıtım, nesneye yönelik programlamada mevcut bir sınıf içinde bulunan veri ve metotların bu sınıftan türetilen alt sınıflar içinde kullanılması olarak tanımlanabilir.

Kendisinden sınıf türetilen sınıf ana, ebeveyn veya süper sınıf olarak, türetilen sınıflar ise çocuk, alt veya uzantı sınıf olarak isimlendirilir.

Bir ana sınıftan yeni bir çocuk sınıf türetildiğinde, ana sınıfta yer alan tüm veri ve metotlar çocuk sınıf tarafından kullanılabileceği gibi, çocuk sınıf içinde de yeni veri ve metotlar tanımlanabilir. Eğer ihtiyaç duyulursa, ana sınıftan devralınan metotlar geçersiz hale getirilir (overriding) ve aynı isim altında farklı kodlar yazılır.

Ana sınıftan bir çocuk sınıf türeterek, ana sınıfta yer alan veri ve metotların devralınması, devralınan metotlar için yeniden kod yazmaya gerek duymadan, ana sınıf içinde yer alan veri ve metotları kullanmaya olanak sağlar.

Çok biçimlilik (Polymorphism)

Çok biçimlilik sözlük anlamı olarak birden fazla şekilde varlık gösterebilen nesne ya da kavramları ifade etmektedir. Nesneye yönelik programlamada ise, çok biçimlilik fonksiyon ve işlemcilerin birden fazla görev için kullanılmaları ile kalıtım ve sanal fonksiyonların kullanılmasını içerir.

C++’da, çok biçimlilik kavramını aşağıda gösterilen dört farklı yöntemle uygulayabiliriz:

  • Fonksiyonlara çoklu görev tanımlama (Overloading) işlemi
  • İşlemcilere çoklu görev tanımlama (Overloading) işlemi
  • Sınıf fonksiyonlarını doğrudan yeniden tanımlama (Overriding)
  • Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama (Overriding)

Fonksiyonlara çoklu görev tanımlama (Overloading) işlemi

C++’da, fonksiyonlar için çoklu görev tanımlama (overloading) işlemi yapılırken çok biçimlilik özelliği kullanılır. Birden fazla fonksiyon, farklı veri türündeki ve/veya farklı sayıda parametrelerle bildirimleri yapıldığında, aynı ismi kullanır ve program içinden farklı parametreler ve aynı isim ile çağrılırlarsa, fonksiyon çoklu görev tanımlama işlemi gerçekleştirilmiş olur. Böylece, program içinde tek bir isim kullanarak birden fazla fonksiyona erişim sağlanabilir. Burada kullanılan çoklu görev tanımlama ifadesi birden fazla fonksiyonun aynı isim ile çağrılarak kullanılmasını gösterir. Böyle bir fonksiyon çağırıldığında, çağrı fonksiyon çağrısında kullanılan parametre sayısı ve tiplerine uygun olarak ilgili fonksiyona yönlendirilir.

İşlemcilere çoklu görev tanımlama (Overloading) işlemi

C++’da, işlemci çoklu görev tanımlama işlemi yapılırken de çok biçimlilik özelliği kullanılır. Bir işlemci için çoklu görev tanımlaması yapıldığında, sahip olduğu özelliklerin yanı sıra, bir sınıfa bağlı olarak ek işlem yapma özelliği kazanır. Bir işlemci için çoklu görev tanımlaması yapıldığında yani birden fazla işlem yapma kapasitesi kazandırıldığında, işlemcinin orjinal fonksiyonu ortadan kalkmaz. İşlemciler için çoklu görev tanımlaması yapmak amacıyla işlemci fonksiyonları oluşturulur. Bir işlemci fonksiyonu, çoklu görev tanımlaması uygulanan işlemcinin bağlı olduğu sınıfa göre gerçekleştireceği işlemleri tanımlar. İşlemci fonksiyonu operator anahtar kelimesi kullanılarak oluşturulur. İşlemci fonksiyonları, bir sınıfın üyesi olabilir veya olmayabilir. Üye olmayan işlemci fonksiyonları, sınıf için friend fonksiyon olarak tanımlanır. İşlemci fonksiyonlarının yapısı sınıf üyesi olma ve olmama durumuna göre farklılık gösterir.

Bir ana sınıftan bir sınıf türetildiğinde, ana sınıfta yer alan tüm veri ve metotlar türetilen sınıf tarafından kullanılabileceği gibi, türetilen sınıf içinde de yeni veri ve metotlar tanımlanabilir. Eğer ihtiyaç duyulursa, ana sınıftan devralınan metotlar geçersiz hale getirilir (overriding) ve aynı isim altında farklı kodlar yazılır. Bu durumda, aynı fonksiyon hem ana sınıfta hem de türetilmiş sınıfta tanımlanmış olur. Bu fonksiyon türetilmiş sınıf nesnesi ile çağrıldığında, türetilmiş sınıfın fonksiyonu çağrılır. Bu özelliğe, Fonksiyonu Yeniden Tanımlama adı verilir. Türetilmiş sınıftaki fonksiyon, ana sınıftaki fonksiyonun yerini alır.

Fonksiyonu yeniden tanımlama işleminin yapılabilmesi için, bir ana sınıftan bir sınıf türetilmesine, kalıtım özelliğinin kullanılmasına, ihtiyaç vardır.

Fonksiyonları yeniden tanımlama işlemi, bir ana sınıf ve ana sınıftan türetilmiş olan bir veya daha fazla türetilmiş sınıf içinde yapılır. Bu işlem iki farklı yöntemle uygulanabilir:

Sınıf fonksiyonlarını doğrudan yeniden tanımlama

Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama

Sınıf fonksiyonlarını doğrudan yeniden tanımlama (Overriding)

Sınıf üye fonksiyonlarını yeniden tanımlama işlemi yaparken, ana sınıf içinde tanımlanan bir fonksiyon ile aynı isme sahip bir fonksiyon ana sınıftan türetilmiş bir sınıf içinde tanımlanır ve kod içeriği yeniden yazılır. Bu durumda, ana sınıf ve bu sınıf içinde aynı isme sahip iki fonksiyon oluşturulur. Bu fonksiyonlara ana sınıf ve türetilmiş sınıftan oluşturulan işaretçi ve nesneler yoluyla yapılan erişimler aşağıda gösterilen esaslara göre yapılmaktadır:

Doğrudan yeniden tanımlama yönteminde, ana sınıf işaretçisine türetilen sınıf nesnesinin adresi atandığında, ana sınıf işaretçisi ana sınıf içindeki fonksiyonlara erişim sağlar.

Sınıf fonksiyonlarını sanal yöntemle (virtual) yeniden tanımlama (Overriding)

Sanal fonksiyonlar, çalışma zamanı çok biçimlilik (Runtime Polymorphism) özelliği sağlar. Sanal bir fonksiyon oluşturmak için, ana sınıf içindeki fonksiyon bildiriminden önce virtual anahtar kelimesi kullanılır. Sanal fonksiyon içeren bir sınıftan yeni bir sınıf türetildiğinde, türetilen her sınıf içinde sanal fonksiyon, virtual anahtar kelimesi kullanılmadan, yeniden tanımlanır ve fonksiyon içeriği yeniden düzenlenir. Bu özellikle, virtual anahtar kelimesi derleyiciye fonksiyon bağlama işlemini derleme zamanında değil çalışma zamanında yapmasını bildirir. Sanal fonksiyon ile, aynı isme sahip bir fonksiyon her sınıf için ayrı bir işlem yapacak şekilde tanımlanabilmektedir. Bu durum nesneye yönelik programlamada çok biçimlilik (Polymorphism) özelliğinin bir sonucudur. İşaretçi kullanarak erişim sağlamak sanal fonksiyonları sınıf içindeki diğer fonksiyonlardan farklı hale getirir. Ana sınıf türünden oluşturulan bir işaretçi ana sınıf ve ana sınıftan türetilen tüm sınıflar içindeki sanal fonksiyonlara erişim sağlayabilir.

Sanal yöntemle yeniden tanımlama yönteminde, ana sınıf işaretçisine türetilen sınıf nesnesinin adresi atandığında, ana sınıf işaretçisi türetilen sınıf içindeki fonksiyonlara erişim sağlar.

Sınıf

Nesneye yönelik programlama (NYP) çalışma sistemi 2 temel kavram üzerinde şekillenir:

  1. Değişkenler (veriler): NYP ile geliştirilen uygulamalarda ihtiyaç duyulan farklı türden değişkenler sınıf içinde tanımlanır.

  2. Değişkenlere işlem yapan fonksiyonlar (metodlar): NYP ile geliştirilen uygulamalarda sınıf içinde tanımlanan değişkenlere işlem yapmak üzere fonksiyonlar içinde kodlar tanımlanır.

NYP ile geliştirilen uygulamalarda program içinde, veriler ile verilere işlem yapacak olan fonksiyonlar (metodlar) sınıf (class) adı verilen yapıların içinde tanımlanır. Sınıf tanımlandıktan sonra bu sınıf türünden bir değişken (nesne) oluşturularak, bu nesne yoluyla sınıf içinde yer alan tüm değişken ve fonksiyonlara erişim sağlanır.

Nesne

Bir nesne oluşturmadan önce, class anahtar kelimesini kullanarak nesnenin tüm özellik (değişkenler) ve davranışlarını (fonksiyonlar) gösteren genel yapısını tanımlamamız gerekir.

Sınıflar class anahtar kelimesi ile oluşturulur. Bir sınıf oluşturulduğunda, sınıf içindeki değişkenlere yine sınıf içindeki fonksiyonların işlem yapmasını sağlayan yeni bir veri türü tanımlanmış olur.

Sınıf adı verilen bu yeni veri türü oluşturulduktan sonra, bu sınıfa ait nesne bildirimi yapılır. Bu işlem, int bir veri türünden değişken tanımlamaya benzer.

C++ Kapsülleme

Kapsülleme, programda bir sınıf içinde tanımlanan verileri ve yine aynı sınıf içinde tanımlanan ve bu verilere erişim sağlayarak kullanan metod veya fonksiyon adı verilen sistemi ifade eder. Bu sistemle, sınıf içinde ye alan veriler ve bu verilere erişim sağlayan kodlar bir bütünlük içinde korunarak, dışarıdan erişimi kısıtlanır. Böylece, program kendi içinde bir kod ve veri güvenliği sağlar. Bu sistemde, kod ve veri tek bir isim altında tanımlanarak, oluşturulan bir sınıf içindeki veri ve kodlar (metodlar) korunur.

Kapsülleme verileri ve bu verileri kullanan ya da değiştiren program kodlarını birbirine bağlayarak dışarıdan yapılabilecek müdahalelere karşı koruyan bir sistemdir. Nesneye yönelik programlamada, bir sınıf tanımlaması altında kod ve veri bu şekilde koruma altına alındığında bir nesne oluşturulmuş olur. Nesne kapsamındaki veri ve verilere işlem yapan kodlar; sadece içinde tanımlı olduğu nesne tarafından (private) veya dışarıdan erişilecek şekilde (public) tanımlanabilir. Nesne içinde private olarak tanımlanmış özel kod ve verilere sadece nesne içinde yer alan diğer kodlar tarafından erişilebilir. Nesne dışında yer alan kodlar nesneye ve özel verilere erişemezler.

Nesne içinde public olarak tanımlanan kod ve veriler tüm erişimlere açık olduğundan, programın nesne dışında kalan kodları bu kod ve verilere erişim sağlar. Nesne içinde programdaki tüm kodların erişimine açık veri ve kodlar açık olarak tanımlanır. Tüm erişimlere açık olan nesne elemanları, nesneye özel elemanlara erişim için kullanılır. Bu durumda, nesne dışındaki kodlar nesne içindeki tüm erişimlere açık kodlar yoluyla nesne içindeki nesneye özel veri ve kodlara da erişebilirler.

Şimdi, kapsülleme özelliğinin çalışma prensibini göstermek amacıyla, bir sınıf içinde bildirimi yapılmış olan private, protected ve public değişkenlere, aynı sınıf türünden oluşturulmuş bir nesne yoluyla erişim koşullarını gösteren bir örneği incelemeye çalışalım:

Örnek

Devamı...

C++ Dinamik bellek kullanımı

C++’da daha kaliteli uygulamalar geliştirmek için dinamik bellek kullanımını etkin bir şekilde kullanmamız gerekmektedir. Program normal koşullarda ihtiyaç duyulan bellek tahsisini ve bellek boşaltma işlemlerini işlem satırlarında yer alan kodlara uygun olarak yapar. Ancak, bazı durumlarda, değişkenlere atanacak verilerin boyutu ve ihtiyaç duyulan bellek miktarı programın çalışması esnasında belirlenebileceğinden, bellek tahsis ve boşaltma işlemlerini program çalışması esnasında dinamik olarak gerçekleştirmek gerekir.

Dizi tanımlaması gibi yapılan bazı işlemler belleğin otomatik olarak tahsis edilmesini sağlarken, bazı işlemler bu olanağı sağlamaz. Bu durumda, programın çalışması esnasında gereksinim duyduğumuzda bellek tahsis edebiliriz. Bu işleme dinamik bellek kullanımı yöntemi adı verilir.

C++ dinamik bellek kullanımı

Program çalışırken dinamik olarak bellek tahsisi heap adı verilen bellek bölgesinden yapılır.

new ve delete işlemcileri

C++’da dinamik bellek işlemleri için new ve delete işlemcileri kullanılır.

new işlemcisi bellek tahsisi yapar ve tahsis edilen belleğin başlangıç adresini geri döndürür. new işlemcisinin genel kullanım şekli aşağıdadır:

veri-türü işaretçi-adı = new veri-türü;

delete işlemcisi daha önce new işlemcisi ile tahsis edilen belleği boşaltır. delete işlemcisinin genel kullanım şekli aşağıdadır:

delete işaretçi-adı;

new işlemcisi, new işlemcisinin sağ tarafındaki veri türü büyüklüğünde bellek tahsis ederek, tahsis edilen belleğin başlangıç adresini geri döndürerek aynı veri türünden bir işaretçiye atar.

Bellek tahsis işleminde meydana gelebilecek sorunlar, genellikle heap bellek alanındaki yetersizlikten ötürü, program tarafından kontrol edilmelidir.

Şimdi, new ve delete işlemcilerinin kullanılmasını bir örnek üzerinde incelemeye çalışalım:

Örnek

Devamı...

C++ Soyutlama

Soyutlama, kullanıcıya yalnızca ilgili ayrıntıların gösterilmesi ve ilgisiz ayrıntıların gizlenmesi olarak ifade edilebilir. C++’da kullanılan temel soyutlama sistemleri sınıflar, sınıflar yoluyla yapılan kalıtım ve şablonlardır.

Soyutlama, genellikle veri soyutlama amacıyla kullanılır. Veri soyutlama kullanımı için, içinde en az bir adet saf sanal fonksiyon bulunan soyut (abstract) bir sınıf oluşturulur. Bir sınıf içinde en az bir adet saf sanal fonksiyon tanımlanırsa, bu sınıf soyut (abstract) sınıf haline gelir. Bu soyut sınıf kendisinden türetilen alt sınıfların ortak değişkenlerini ve fonksiyonlarını içerir. Soyut bir sınıftan türetilen tüm sınıflarda sanal fonksiyon bildirimi yeniden yapılmalıdır. Eğer yapılmazsa, türetilen sınıflarda soyut sınıf olarak kabul edilir. Soyut sınıflar saf sanal fonksiyon dışında normal fonksiyonlar ve değişkenler içerebilir.

Soyut sınıfları kullanılarak geliştirilen yazılımlarda değişiklik yapmak gerektiğinde, soyut sınıflarda yer alan ve türetilen sınıflar tarafından kullanılan private erişim özelliğine değişkenlerin değiştirilmesi yeterli olmaktadır. Soyut sınıflarda bildirimi yapılan private değişkenler veri güvenliğini artırır ve program kodlarının daha pratik yazılmasını sağlar.

C++ Veri türü tanımlama (Typedef)

typedef ifadesini kullanarak, standart veri türlerinini (int, char, float, vs.) veya kullanıcı tanımlı yapıları farklı isimlerle tanımlayabiliriz. Bu şekilde mevcut bir veri türü için yeni bir isim veya yeni bir veri türü oluşturabiliriz. typedef ifadesinin genel yapısı aşağıdaki gösterilmektedir:

Devamı...

C++ Bileşimler (Unions)

Bileşim, iki veya daha fazla değişken tarafından ortaklaşa kullanılan tek bir bellek birimidir. Burada bahsi geçen değişkenler farklı veri türünden olabilir. Ancak, aynı bellek bölgesini paylaşan değişkenlerden sadece bir tanesi aynı anda bellek bölgesini kullanabilir. Genel görünüşü ile yapılara benzeyen bileşimlerin genel yapısı aşağıdaki gösterilmektedir:

Devamı...

C++ Yapılar (Structures)

Daha önce, aynı türden olan verileri diziler içinde tanımladıktan sonra, sadece bir dizi ismini kullanarak bu verilere erişim sağladığımızı gördük. Türleri farklı olan verileri tek bir isim altında toplayabilmemiz için ise, yapı (structure) adı verilen kullanıcı tanımlı veri türlerini kullanabiliriz.

Yapı, farklı veri türlerini bir grup altında toplayan kullanıcı tanımlı bir veri türüdür. İki veya daha fazla elemandan oluşur. Bir yapı içindeki bütün veri tipleri aynı olabileceği gibi, her veri türü birbirinden farklı da olabilir.

Yapı bildirimi

Yapıları tanımlamak için aşağıda gösterilen üç yöntemden birini kullanabiliriz::

Devamı...

C++ dosya Giriş/Çıkış (I/O)

Dosya giriş/çıkış işlemlerini gerçekleştirmek için programlarımızın başına başlık dosyasını eklememiz gerekir. Bu dosyada [ifstream](https://sonsuzus.github.io/search.html?q=ifstream), [ofstream](https://sonsuzus.github.io/search.html?q=ofstream) ve [fstream](https://sonsuzus.github.io/search.html?q=fstream) sınıflarının da yer aldığı bazı sınıf bildirimleri yer alır. Bu sınıflar sırasıyla, ios sınıfından türetilen istream, ostream ve iostream sınıflarından türetilmiş olduğundan, ios sınıfı içindeki tüm değişken ve fonksiyonlara erişim sağlayabilirler.

Ana sınıf Türetilmiş sınıf Türetilenden türetilmiş sınıf
ios istream ifstream
ios ostream ofstream
ios iostream fstream

Dosya açma ve kapama işlemleri

C++’da, bir dosyayı açmak için akışları kullanabiliriz. Giriş, çıkış ve giriş/çıkış olmak üzere üç tür akış vardır. Giriş akışı oluşturmak için akışı ifstream sınıfı olarak, çıkış akışı oluşturmak için akışı ofstream sınıfı olarak ve giriş ve çıkış işlemlerinin her ikisini gerçekleştirmek için akışı fstream sınıfı olarak bildirmemiz gerekir.

Aşağıdaki ifadeler bir adet giriş, bir adet çıkış ve bir adet hem giriş hem de çıkış işlemi yapan bir adet akış oluşturur:

Devamı...

C++ C dosya Giriş/Çıkış (I/O)

Bu bölümde, C temelli dosya giriş ve çıkış işlemlerini incelemeye çalışacağız. Bu işlemler üzerinde çalışmaya başlamadan önce, akış ve dosya kavramlarını ayrı ayrı ele alalım:

Akış

Dosya sistemi farklı donanım elemanları ile çalışma olanağı sağlar. Bu donanım elemanı bir klavye, ekran, disk sürücü veya bilgisayarda kullanılan bir port olabilir.

Dosya giriş çıkış işlemlerinin temelini, bilgisayarı oluşturan aygıtlar için mantıksal bir arabirim görevi yapan, Akış adı verilen bir kavram oluşturur. Genel bir ifade ile, akış bir dosyaya ulaşmak için kullanabileceğiniz mantıksal bir ara birimdir. Ancak burada kullanılan dosya ifadesi, diske kaydedilebilen bir dosyayı ifade etmekle birlikte, ekran ve klavye gibi donanım elemanlarından birini de ifade edebilir. Dosyaların yapıları veya kapasiteleri farklı olabilir, ancak akışların tamamı aynıdır. Bu özellik, donanım elemanlarını benzer şekilde tanımlama olanağı sağlar. Yani, dosya sistemi bu farklı donanım elemanlarını akış vasıtası ile benzer elemanlar gibi kullanabilir. Böylece, disk üzerindeki bir dosyaya yazı yazmak için kullandığınız fonksiyonları, aynı zamanda ekrana ve yazıcıya yazı yazmak için de kullanabiliriz.

Akış, stdio.h başlık dosyası içinde tanımlı FILE adlı yapı veri türünden bildirimi yapılan bir işaretçi değişkeni ile kullanılan bir dosya veya fiziksel bir cihazdır.

Bir akışın dosya (fiziksel aygıtlar dahil) ile bağlantısını sağlamak için açma işlemi, dosyadan bağlantısını kesmek için kapama işlemi uygulanır. Dosya açıldıktan sonra, dosyadan programımıza bilgi aktarabilir veya dosya içeriğini değiştirebiliriz.

2 tür akış vardır:

  1. Metin akışı
  2. İkili sistem akışı

Metin Akışı

Metin akışı, herhangi bir metin editörü ile oluşturulan DOS metin dosyaları ile kullanılır. Yani, metin akışı ASCII karakterlerle birlikte kullanılır. Metin akışı, metin dosyalarını satırları tek bir yeni satır karakteri (ASCII 10 = Line feed = LF = \n) ile ayrılmış olarak dikkate alır. Ancak, DOS metin dosyaları, her satırı arasında bir yeni satır (ASCII 10 = Line feed = LF = \n) ve bir satır başı (ASCII 13 = Carriage return = CR = \r) karakteri olmak üzere toplam iki karakter ile, diske kaydedilir. Metin akışına diskten bir dosya okurken yeni satır ve satır başı karakterleri tek bir yeni satır karakterine çevrilir. Metin akışından diske bir dosyayı kaydederken ise, tek bir yeni satır karakteri, yeni satır ve satır başı karakterlerine çevrilir. Bu nedenle, metin akışına gönderilen ifadelerle dosyaya yazılan ifadeler birebir aynı olmayabilir.

İkili sistem akışı

İkili sistem akışında ise, herhangi bir karakter dönüşümü yapılmaz. Yani, ikili akıştan diske bir dosya kaydederken veya diskten ikili bir dosya aktarırken, dosya içinde yer alan karakterlerde herhangi bir değişiklik yapılmaz. İkili sistem akışına gönderilen ifadelerle dosyaya gönderilen ifadeler tamamen birbirinin aynıdır.

Aktif konum

Aktif konum, bir dosyaya yapılacak bir sonraki girişin yapılacağı konumdur. Örneğin, 80 byte uzunluğunda bir dosyanın ilk erişimde 20 byte’ının okunduğunu kabul edelim. Bir sonraki dosya okuma işlemi 21 nci byte dan başlayacaktır. Bu durumda, 21 nci byte aktif konum olarak kabul edilir. Başka bir ifade ile, dosya işlemlerinde yapılan bir sonraki işlem dosya başından değil kalınan yerden devam eder.

Dosya sistemi

Dosya sisteminde kullanılan dosya kavramı, normal bir disk dosyası için kullanılabileceği gibi, ekran, klavye gibi bilgisayar parçaları içinde kullanılabilir.

Bir dosya açıldığında, aktif konum göstergesi dosya başlangıcını gösterir. Dosyadan her okuma ve yazma işleminde, aktif konum göstergesi otomatik olarak bir sonraki konuma geçer.

Standart kütüphane fonksiyonlarını kullanarak, dosya aktif konumunu başa alabilir veya belirli bir konuma taşıyabiliriz.

Standart akışlar

Bir programı çalıştırdığımızda, program aşağıda gösterilen standart metin akışlarını otomatik olarak açar. Bu metin akışları yoluyla, program bilgisayara bağlı aygıtlara (Klavye, ekran, yazıcı gibi…) tıpkı bir dosya gibi erişebilir:

Devamı...