Sınıf Nedir
Sınıf, veriyi (üye değişkenler) ve davranışı (üye fonksiyonlar) tek bir birimde bir araya getiren özel bir tip için tasarım planıdır. int ve double gibi yerleşik tipler tek tek değerleri tanımlarken, bir sınıf bütün bir kavramı - bir banka hesabını, 2B bir noktayı, bir oyuncuyu - etrafta dolaştırabileceğin tek bir değer olarak modellemene olanak tanır.
Hiç tanımlamadan da sınıfları zaten kullandın: std::string ve std::vector standart kütüphaneden gelen sınıflardır. name.length() ya da v.push_back(3) çağırmak, bir nesne üzerinde bir üye fonksiyon çağırmaktır. Şimdi kendi tiplerini aynı şekilde inşa edecek, ardından onları ilklendirmek için kuruculara geçeceksin.
Bir Sınıf Tanımlama ve Nesne Oluşturma
Bir sınıf tanımı üyelerini süslü parantezler arasında listeler ve noktalı virgülle biter - o sondaki ;'yi unutmak, yeni başlayanların en sık yaptığı hatalardan biridir. Sınıftan oluşturduğun her nesne üye değişkenlerin kendi kopyasına sahip olur.
rex ve luna iki ayrı nesnedir. rex.name'i değiştirmek luna.name'e dokunmaz - her nesne kendi verisini tutar. Bir nesnede bir üyeye nokta operatörü . ile erişirsin (ya da bir nesneye işaretçin varsa -> ile).
public ve private
Varsayılan olarak bir class içindeki her şey private'tır: ona yalnızca sınıfın kendi üye fonksiyonları dokunabilir. public: etiketi üyeleri dış koda açar. Bu ayrım kapsüllemenin (encapsulation) kalbidir - güvenli bir arayüz sunar ve dahili veriyi gizlersin, böylece veri geçersiz bir duruma sokulamaz.
count private olduğu için hiçbir çağıran negatif ya da anlamsız bir değeri içeri sokamaz - increment() üzerinden geçmek zorundadırlar. value()'nun parametre listesinden sonraki const, fonksiyonun nesneyi değiştirmeyeceğine söz verir; bu da onu const nesneler üzerinde çağırmana olanak tanır ve okuyanlara niyeti belli eder. public, private ve protected hakkında tüm hikaye için erişim belirleyicilerine bak.
Metotların Bildirimi ile Tanımı
Küçük sınıflar için metotları satır içi tanımlamak (yukarıdaki gibi) gayet uygundur. Daha büyük sınıflarda ise metotları sınıfın içinde bildirmek ve gövdelerini ClassName::method kapsam söz dizimiyle dışarıda tanımlamak yaygındır. Bu, sınıf tanımını arayüzün bir özeti olarak okunabilir tutar.
Rectangle:: öneki, fonksiyonun hangi sınıfa ait olduğunu derleyiciye söyler. Böyle bir tanımın içinde üyelere yine yalın adlarıyla (width, area()) başvurursun - derleyici onların, metodun üzerinde çağrıldığı nesneye ait olduğunu bilir.
this İşaretçisi
Statik olmayan herhangi bir üye fonksiyonun içinde this, fonksiyonun üzerinde çağrıldığı nesneye işaret eden bir işaretçidir. Genellikle ona ihtiyacın olmaz, çünkü yalın bir üye adı zaten geçerli nesneye işaret eder. Asıl işe yaradığı an, bir parametrenin bir üyeyi gölgelediği (shadow) - aynı adı paylaştıkları - ve ayrım yapman gereken durumdur.
this-> olmadan, setX içinde x = x; yazmak parametreyi kendisine atar ve üyeye hiç dokunmaz - sessiz bir hata. this->x bunu kesinleştirir. Birçok kod tabanı, parametrelere farklı adlar vererek (örneğin setX(int newX)) bu sorunu tamamen önler, ama gerçek kodda this->'i sürekli göreceksin.
Sık Yapılan Hatalar
Birkaç sınıf tuzağı insanları tekrar tekrar yakalar:
- Kapanış noktalı virgülünü unutmak. Bir sınıf tanımı
};ile biter.;'yi atarsan, sınıfın kendisini değil, sınıftan sonra geleni gösteren bir yığın kafa karıştırıcı hatayla karşılaşırsın. - Üyeleri ilklendirmeyi unutmak.
intvedoublegibi yerleşik üyeler otomatik olarak sıfırlanmaz. İlklendirilmemiş bir üyeyi okumak tanımsız davranıştır. Üyelere varsayılan değerler ver (int count = 0;) ya da onları bir kurucuda ilklendir. - private üyelere dışarıdan erişmek. Bir private üye üzerinde
c.count = 5;bir derleme hatasıdır - bunun yerine public bir metot kullan. Bu, kapsüllemenin amaçlandığı gibi çalışmasıdır. - Sınıfı nesneyle karıştırmak.
Dog.bark();yanlıştır -Dogtiptir. Metotları nesneler üzerinde çağırırsın:rex.bark();.
// İlklendirilmemiş üye - 'age'i okumak tanımsız davranıştır:
class Cat {
public:
int age; // varsayılan değer yok
};
Cat c;
std::cout << c.age; // çöp değer, 0 değil
Sıradaki: Kurucular
Bir nesne oluşturduktan sonra her üyeyi elle atamak - rex.name = ...; rex.age = ...; - sıkıcıdır ve unutması kolaydır; ilklendirilmemiş üyelerle tam da böyle baş başa kalırsın. Sonraki sayfa kurucuları ele alıyor: bir nesne oluşturulduğunda otomatik olarak çalışan özel fonksiyonlar; bunlar sayesinde her nesnenin geçerli bir durumda başlamasını temiz, tek satırlık bir Dog rex("Rex", 4); söz dizimiyle garanti edebilirsin.
Sıkça Sorulan Sorular
C++'ta sınıf ile nesne arasındaki fark nedir?
Bir sınıf tasarım planıdır - bir tipin hangi veriye (üye değişkenler) ve hangi davranışa (üye fonksiyonlar) sahip olduğunu tanımlar. Bir nesne ise bu plandan üretilen somut bir örnektir. class Dog { ... }; tipi bir kez tanımlar; Dog rex; kullanabileceğin gerçek bir Dog oluşturur. Tek bir sınıf birbirinden bağımsız birçok nesne üretebilir.
C++'ta class ile struct arasındaki fark nedir?
Teknik olarak tek fark varsayılan erişim düzeyidir: bir class'ın üyeleri varsayılan olarak private, bir struct'ın üyeleri ise varsayılan olarak public'tir. İkisinin de üye fonksiyonları, kurucuları ve kalıtımı olabilir. Geleneksel olarak struct düz veri demetleri için, class ise davranışı ve korunması gereken değişmezleri olan tipler için kullanılır.
C++ sınıfında this işaretçisi ne yapar?
Bir üye fonksiyonun içinde this, fonksiyonun üzerinde çağrıldığı nesneye işaret eden bir işaretçidir. Bir parametreyi bir üyeden ayırt etmek (this->x = x;) ya da geçerli nesneyi döndürmek için kullanılır. Normal üye erişiminde ona nadiren ihtiyaç duyarsın - sadece x yazmak zaten geçerli nesnenin x'ine işaret eder.