Yapıcı İlklendirme Listeleri
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 22 / 104.
Önceki derslerde Player(std::string n, int h) : name(n), health(h) {} gibi iki nokta üst üste sözdizimini görmüştünüz. Buna bir üye başlatıcı listesi denir ve C++'ta üyeleri başlatmak için tercih edilen yoldur.
Başlatıcı listesi, yapıcı metodun parametre listesinden sonra gelir ve iki nokta üst üste ile başlar. Her bir üye, virgüllerle ayrılmış şekilde doğrudan kendi değeriyle başlatılır:
class Rectangle {
int width;
int height;
const int id;
int& reference;
public:
Rectangle(int w, int h, int i, int& r)
: width(w), height(h), id(i), reference(r) {
// Yapıcı gövdesi (boş olabilir)
}
};Neden yapıcı (constructor) gövdesinde atama yerine başlatıcı listeleri (initializer lists) kullanılmalı? Atama ile üyeler önce varsayılan olarak oluşturulur (default-constructed), ardından yeni değerler atanır. Başlatıcı listeleri ile üyeler doğrudan doğru değerlerle oluşturulur; bu daha verimlidir ve bazen zorunludur.
Belirli üyelerin liste kullanılarak ilklendirilmesi zorunludur:
constüyeleri - oluşturulduktan sonra atanamaz
- Referans üyeler - ilklendirme sırasında bağlanmalıdır
- Varsayılan yapıcıları olmayan üyeler
class Player {
const int maxHealth; // Başlatıcı listesi kullanılmalıdır
std::string name;
public:
// Bu çalışır
Player(int max, std::string n) : maxHealth(max), name(n) {}
// Bu derlenmeyecektir:
// Player(int max) { maxHealth = max; } // Hata!
};Üyeler, başlatıcı listesindeki sıraya göre değil, sınıf içinde bildirildikleri sıraya göre başlatılır. Karışıklığı önlemek için başlatıcı listenizi her zaman bildirim sırasına göre yazın.
Görev
KolayÜye başlatıcı listelerinin (member initializer lists) ne zaman ve neden gerekli olduğunu gösteren bir oyun motoru yapılandırma sistemi oluşturalım. Başlatıcı listesi sözdizimi kullanılarak başlatılması zorunlu olan üyelere sahip bir GameConfig sınıfı oluşturacaksınız.
Kodunuzu düzenlemek için iki dosya oluşturacaksınız:
GameConfig.h: Oyun ayarlarını saklayan birGameConfigsınıfı tanımlayın. Sınıfınız şunlara sahip olmalıdır:- Bir
const std::string gameName— oyunun başlığı, oluşturulduktan sonra değiştirilemez - Bir
const int maxPlayers— maksimum oyuncu sayısı, oluşturma sırasında sabitlenir - Bir
int& difficultyRef— harici bir zorluk ayarına referans - Bir
int screenWidthveint screenHeight— ekran ayarları için normal üyeler - Gerekli tüm parametreleri alan ve her üyeyi başlatıcı listesini kullanarak başlatan bir kurucu (constructor). Başlatıcı listesi, üyelerin sınıfta bildirilme sırasını takip etmelidir
- Yapılandırmayı şu formatta yazdıran bir
display()metodu:Game: <gameName> Max Players: <maxPlayers> Difficulty: <difficultyRef value> Resolution: <screenWidth>x<screenHeight>
- Bir
main.cpp: Girişten yapılandırma değerlerini okuyun ve bir GameConfig nesnesi oluşturun. Şunları yapmanız gerekecek:- Girişten oyun adını (string), maksimum oyuncu sayısını (int), zorluğu (int), genişliği (int) ve yüksekliği (int) okuyun — her biri ayrı bir satırda
- Yapılandırmanın referans alacağı zorluk için yerel bir
intdeğişkeni oluşturun - Başlatıcı listesi kurucusunu kullanarak bir
GameConfignesnesi oluşturun - Başlangıç yapılandırmasını göstermek için
display()metodunu çağırın - Zorluk değişkenini doğrudan değiştirin (2 ile çarpın)
"After difficulty change:"yazdırın- Referansın güncellenmiş değeri yansıttığını göstermek için
display()metodunu tekrar çağırın
Bu meydan okuma, başlatıcı listelerinin neden önemli olduğunu vurgular: const üyeleriniz ve referans üyeniz kurucu gövdesinde atanamaz — listede başlatılmalıdırlar. Referans üyesi ayrıca orijinal değişkendeki değişikliklerin yapılandırma nesnesi aracılığıyla nasıl yansıtıldığını gösterir.
Başlık dosyanızı main.cpp içine #include "GameConfig.h" kullanarak dahil edin.
Kopya kağıdı
Bir üye ilklendirme listesi (member initializer list), C++'da sınıf üyelerini ilklendirmek için tercih edilen yoldur. Yapıcı fonksiyonun (constructor) parametre listesinden sonra, bir iki nokta üst üste ile başlayarak görünür ve her bir üye doğrudan ilklendirilir:
class Rectangle {
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {
// Yapıcı gövdesi
}
};Neden ilklendirme listeleri kullanılır? Üyeler, varsayılan olarak oluşturulup sonra atanmak yerine doğrudan doğru değerlerle oluşturulur, bu da işlemi daha verimli hale getirir.
Belirli üyeler için gereklidir:
constüyeler - oluşturulduktan sonra atama yapılamaz- Referans üyeler - ilklendirme sırasında bağlanmalıdır
- Varsayılan yapıcısı (default constructor) olmayan üyeler
class Player {
const int maxHealth;
int& reference;
public:
// Doğru - ilklendirme listesi kullanır
Player(int max, int& r) : maxHealth(max), reference(r) {}
// Hata - gövde içinde const veya referans atanamaz
// Player(int max) { maxHealth = max; }
};Önemli: Üyeler, ilklendirme listesindeki sıraya göre değil, sınıfta bildirildikleri sıraya göre ilklendirilir. İlklendirme listenizi her zaman bildirim sırasına göre yazın.
Kendin dene
#include <iostream>
#include <string>
#include "GameConfig.h"
using namespace std;
int main() {
// Girdi değerlerini oku
string gameName;
getline(cin, gameName);
int maxPlayers;
cin >> maxPlayers;
int difficulty;
cin >> difficulty;
int width;
cin >> width;
int height;
cin >> height;
// TODO: Başlatıcı liste (initializer list) yapıcısını kullanarak bir GameConfig nesnesi oluşturun
// Yapıcı şunları almalıdır: gameName, maxPlayers, difficulty (referans ile), width, height
// TODO: Başlangıç yapılandırmasını göstermek için display() fonksiyonunu çağırın
// TODO: difficulty değişkenini doğrudan değiştirin (2 ile çarpın)
// TODO: "After difficulty change:" yazdırın
// TODO: Güncellenmiş yapılandırmayı göstermek için display() fonksiyonunu tekrar çağırın
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic Konteyner