Sınıf Şablonları
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 65 / 104.
Fonksiyon şablonlarının türden bağımsız fonksiyonlar yazmanıza olanak tanıdığı gibi, sınıf şablonları da türden bağımsız sınıflar oluşturmanıza olanak tanır. std::vector gibi konteynerler bu şekilde çalışır; yapıyı bir kez tanımlarsınız ve derleyici kullandığınız her tür için özel sürümler üretir.
template <typename T>
class Box {
T value;
public:
Box(T v) : value(v) {}
T getValue() const { return value; }
void setValue(T v) { value = v; }
};
int main() {
Box<int> intBox(42);
Box<std::string> strBox("Hello");
std::cout << intBox.getValue() << std::endl; // 42
std::cout << strBox.getValue() << std::endl; // Hello
}Fonksiyon şablonlarının aksine, sınıf şablonlarından nesneler oluştururken açılı ayraçlar kullanarak türü açıkça belirtmelisiniz. Derleyici daha sonra o belirli tür için eksiksiz bir sınıf tanımı oluşturur.
Sınıf şablonları birden fazla tür parametresine ve hatta tam sayılar gibi tür olmayan parametrelere sahip olabilir:
template <typename T, int Size>
class FixedArray {
T data[Size];
public:
T& operator[](int index) { return data[index]; }
int size() const { return Size; }
};
FixedArray<double, 5> arr; // 5 double'lık dizi
arr[0] = 3.14;Üye fonksiyonları sınıf dışında tanımlarken, şablon bildirimini (template declaration) tekrarlamanız gerekir:
template <typename T>
class Container {
T* data;
public:
Container();
~Container();
};
template <typename T>
Container<T>::Container() : data(nullptr) {}
template <typename T>
Container<T>::~Container() { delete data; }Sınıf şablonları, C++'da genel programlamanın temelini oluşturur ve her türle çalışan yeniden kullanılabilir veri yapıları yazmanıza olanak tanır.
Görev
KolayHerhangi bir veri türünü tutabilen esnek bir kapsayıcı oluşturmak için sınıf şablonlarını (class templates) kullanarak genel bir depolama sistemi inşa edelim. Şablon sınıfınızı bir başlık dosyasında düzenleyecek ve ana programınızda farklı türlerle çok yönlülüğünü göstereceksiniz.
İki dosya oluşturacaksınız:
Storage.h: Bazı yararlı işlemlerle birlikte tek bir değer için basit bir kapsayıcı görevi görenStorageadlı bir sınıf şablonu tanımlayın:Storageşablonunuz şunlara sahip olmalıdır:- Saklanan değeri tutmak için özel (private) bir üye
- Başlangıç değeri alan bir yapıcı (constructor)
- Saklanan değeri döndüren bir
getValue()metodu - Saklanan değeri güncelleyen bir
setValue()metodu - Eğer değer, T türünün varsayılan oluşturulmuş (default-constructed) değerine eşitse
true, aksi takdirdefalsedöndüren birisEmpty()metodu
Ayrıca, birbiriyle ilişkili iki değeri saklayan, iki tür parametresine sahip
Pairadlı bir sınıf şablonu oluşturun:- Birinci ve ikinci değerler için (potansiyel olarak farklı türlerde) özel (private) üyeler
- Her iki değeri de başlatan bir yapıcı (constructor)
- Her bir değeri almak için
getFirst()vegetSecond()metodları - Şunu yazdıran bir
display()metodu:(<first>, <second>)
main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):- Bir tam sayı (integer) değeri
- Yeni bir tam sayı değeri
- Bir dize (string) değeri
- Bir ondalıklı sayı (double) değeri
Şablonlarınızı şu şekilde gösterin:
- İlk tam sayı ile bir
Storage<int>oluşturun ve şunu yazdırın:Int storage: <value> setValue()kullanarak ikinci tam sayı ile güncelleyin, ardından şunu yazdırın:Updated: <value>- Dize girdisi ile bir
Storage<std::string>oluşturun ve şunu yazdırın:String storage: <value> - Dize depolamasının boş olup olmadığını kontrol edin ve şunu yazdırın:
Is empty: <true/false>(trueveyafalseyazdırın) - Dize ve ondalıklı sayı değerleri ile bir
Pair<std::string, double>oluşturun, ardındandisplay()metodunu çağırın - Her iki tam sayı girdisi ile bir
Pair<int, int>oluşturun, ardındandisplay()metodunu çağırın
Örneğin, 42, 100, Hello ve 3.14 girdileriyle:
Int storage: 42
Updated: 100
String storage: Hello
Is empty: false
(Hello, 3.14)
(42, 100)Aynı Storage şablonunun tam sayılar ve dizelerle nasıl sorunsuz çalıştığına ve Pair yapısının farklı türleri nasıl bir araya getirebildiğine dikkat edin. Derleyici, kullandığınız her tür kombinasyonu için ayrı sınıf tanımları oluşturur. Tek tür şablonları için template <typename T> sözdizimini, birden fazla tür parametresine sahip şablonlar için ise template <typename T, typename U> sözdizimini kullanmayı unutmayın.
Kopya kağıdı
Sınıf şablonları, türden bağımsız sınıflar oluşturmanıza olanak tanır. Derleyici, kullandığınız her tür için özel sürümler oluşturur.
Temel Sınıf Şablonu
template <typename T>
class Box {
T value;
public:
Box(T v) : value(v) {}
T getValue() const { return value; }
void setValue(T v) { value = v; }
};Sınıf şablonlarından nesne oluştururken, açılı ayraçları kullanarak türü açıkça belirtmelisiniz:
Box<int> intBox(42);
Box<std::string> strBox("Hello");Birden Fazla Tür Parametresi
Sınıf şablonları birden fazla tür parametresine sahip olabilir:
template <typename T, typename U>
class Pair {
T first;
U second;
public:
Pair(T f, U s) : first(f), second(s) {}
};Tür Olmayan Parametreler
Şablonlar ayrıca tam sayılar gibi tür olmayan parametreleri de kabul edebilir:
template <typename T, int Size>
class FixedArray {
T data[Size];
public:
int size() const { return Size; }
};
FixedArray<double, 5> arr; // Array of 5 doublesÜye Fonksiyonları Sınıf Dışında Tanımlama
Üye fonksiyonları sınıf dışında tanımlarken, şablon bildirimini tekrarlayın:
template <typename T>
class Container {
T* data;
public:
Container();
~Container();
};
template <typename T>
Container<T>::Container() : data(nullptr) {}
template <typename T>
Container<T>::~Container() { delete data; }Kendin dene
#include <iostream>
#include <string>
#include "Storage.h"
using namespace std;
int main() {
// Girdileri oku
int intValue1;
int intValue2;
string strValue;
double doubleValue;
cin >> intValue1;
cin >> intValue2;
cin >> strValue;
cin >> doubleValue;
// TODO: İlk tam sayı ile Storage<int> oluştur ve yazdır: Int storage: <value>
// TODO: setValue() kullanarak ikinci tam sayı ile güncelle, yazdır: Updated: <value>
// TODO: String girdisi ile Storage<std::string> oluştur, yazdır: String storage: <value>
// TODO: String deposunun boş olup olmadığını kontrol et, yazdır: Is empty: true/false
// TODO: String ve double ile Pair<std::string, double> oluştur, display() fonksiyonunu çağır
// TODO: Her iki tam sayı ile Pair<int, int> oluştur, display() fonksiyonunu çağır
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