Temsilci Yapıcılar
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 23 / 104.
Ortak başlatma mantığını paylaşan birden fazla kurucunuz olduğunda, kod tekrarını önlemek için devreden kurucular (delegating constructors) kullanabilirsiniz. Bir devreden kurucu, kendi başlatıcı listesinde aynı sınıfın başka bir kurucusunu çağırır.
class Player {
std::string name;
int health;
int level;
public:
// Birincil kurucu - asıl işi yapar
Player(std::string n, int h, int lvl)
: name(n), health(h), level(lvl) {}
// Birincil kurucuya delege eder
Player(std::string n) : Player(n, 100, 1) {}
// Varsayılan kurucu da delege eder
Player() : Player("Unknown") {}
};Delegasyon, sınıf adının ardından argümanların kullanıldığı başlatıcı listesinde gerçekleşir. Player() çağrıldığında, Player(std::string) yapıcısına delege eder, o da daha sonra üç parametreli yapıcıya delege eder. Zincir, hedef yapıcıdan orijinal yapıcıya doğru yürütülür.
Önemli bir kural vardır: delege eden bir kurucu (delegating constructor), başlatıcı listesinde (initializer list) başka üyelere sahip olamaz. Delege etme işlemi listedeki tek öğe olmalıdır:
class Item {
int id;
int value;
public:
Item(int i, int v) : id(i), value(v) {}
// Hata! Delegasyon ile üye ilklendirme bir arada kullanılamaz
// Item(int i) : Item(i, 0), id(i) {}
// Doğru - sadece delegasyon
Item(int i) : Item(i, 0) {}
};Temsilci kurucular (delegating constructors), başlatma mantığını tek bir yerde merkezileştirmeye yardımcı olarak kodunuzun bakımını kolaylaştırır ve yinelenen kodlardan kaynaklanan hatalara karşı daha az eğilimli hale getirir.
Görev
KolayKurucu delegasyonunun (delegating constructors), kurucu çağrılarını birbirine zincirleyerek kod tekrarını nasıl ortadan kaldırabileceğini gösteren bir bağlantı ayarları sistemi oluşturalım.
Kodunuzu düzenlemek için iki dosya oluşturacaksınız:
Connection.h: Çeşitli yapılandırma seçeneklerine sahip bir ağ bağlantısını temsil eden birConnectionsınıfı tanımlayın. Sınıfınız şunlara sahip olmalıdır:- Özel (private) üyeler:
host(string),port(int),timeout(saniye cinsinden int) vesecure(bool) - Dört parametrenin tamamını alan ve bir başlatıcı listesi (initializer list) kullanarak tüm üyeleri başlatan bir birincil kurucu (primary constructor). Bu kurucu
"Connection configured: <host>:<port>"metnini yazdırmalıdır. - Yalnızca
hostveportalan,timeoutdeğerini varsayılan olarak30vesecuredeğerini varsayılan olarakfalseyaparak birincil kurucuya delege eden bir kurucu. - Yalnızca
hostalan veportdeğerini varsayılan olarak80yaparak iki parametreli kurucuya delege eden bir kurucu. hostdeğerini varsayılan olarak"localhost"yaparak tek parametreli kurucuya delege eden bir varsayılan kurucu (default constructor).- Şu formatta bir string döndüren bir
getInfo()metodu:"<host>:<port> (timeout: <timeout>s, secure: <yes/no>)"
- Özel (private) üyeler:
main.cpp: Farklı kurucuları kullanarak bağlantılar oluşturarak delegasyon zincirini gösterin. Girişten bir host adı ve bir port numarası okuyun (her biri ayrı bir satırda), ardından:- Varsayılan kurucuyu kullanarak bir
Connectionoluşturun. - Yalnızca girişten alınan host'u kullanarak bir
Connectionoluşturun. - Girişten alınan hem host hem de port'u kullanarak bir
Connectionoluşturun. - Giriş host'u, giriş port'u,
60timeout değeri vetrueolarak ayarlanmış secure değeri ile birConnectionoluşturun. - Her bağlantı için
getInfo()sonucunu her satıra bir tane gelecek şekilde yazdırın.
- Varsayılan kurucuyu kullanarak bir
Delegasyon zinciri şu şekilde ilerler: varsayılan kurucu tek parametreli kurucuyu çağırır, o iki parametreli kurucuyu çağırır, o da birincil dört parametreli kurucuyu çağırır. Bu, "Connection configured" mesajının oluşturulan her nesne için her zaman birincil kurucudan bir kez yazdırılacağı anlamına gelir.
getInfo() içindeki secure durumu için, secure true ise "yes", aksi takdirde "no" yazdırın.
Başlık dosyanızı main.cpp içine #include "Connection.h" kullanarak dahil edin.
Kopya kağıdı
Bir delegating constructor (devreden kurucu), kod tekrarını önlemek için başlatıcı listesinde (initializer list) aynı sınıfın başka bir kurucusunu çağırır:
class Player {
std::string name;
int health;
int level;
public:
// Birincil kurucu
Player(std::string n, int h, int lvl)
: name(n), health(h), level(lvl) {}
// Birincil kurucuya devreder
Player(std::string n) : Player(n, 100, 1) {}
// Varsayılan kurucu da devreder
Player() : Player("Unknown") {}
};Devretme işlemi, başlatıcı listesinde sınıf adının ardından argümanların kullanılmasıyla gerçekleşir. Kurucular, birinin diğerine devrettiği bir devretme zinciri oluşturabilir.
Önemli kural: Bir delegating constructor, başlatıcı listesinde başka üyelere sahip olamaz. Devretme işlemi listedeki tek öğe olmalıdır:
class Item {
int id;
int value;
public:
Item(int i, int v) : id(i), value(v) {}
// Hata! Devretme ile üye başlatma karıştırılamaz
// Item(int i) : Item(i, 0), id(i) {}
// Doğru - sadece devretme
Item(int i) : Item(i, 0) {}
};Kendin dene
#include <iostream>
#include <string>
#include "Connection.h"
using namespace std;
int main() {
// Girdiyi oku
string host;
int port;
cin >> host;
cin >> port;
// TODO: Varsayılan yapıcıyı (default constructor) kullanarak bir Connection oluşturun
// TODO: Sadece girdiden alınan host bilgisini kullanarak bir Connection oluşturun
// TODO: Girdiden alınan hem host hem de port bilgilerini kullanarak bir Connection oluşturun
// TODO: Girdi host, girdi port, timeout=60 ve secure=true parametreleriyle bir Connection oluşturun
// TODO: Her bağlantı için getInfo() sonucunu her satıra bir tane gelecek şekilde yazdı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