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ı sağlaması gibi, sınıf şablonları da türden bağımsız sınıflar oluşturmanı sağlar. std::vector gibi kapsayıcılar bu şekilde çalışır: yapıyı bir kez tanımlarsın ve derleyici, kullandığın her tür için belirli sürümler oluşturur.
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; // Merhaba
}Sınıf şablonlarından nesneler oluştururken türü genellikle açılı ayraçlar içinde belirtirsin. C++17'den beri derleyici, türü kurucu bağımsız değişkenlerinden de çıkarabilir (Box b(42); bir Box<int> oluşturur); ancak türü çıkarabileceği hiçbir bağımsız değişken yoksa türü yazmalısın. Derleyici daha sonra bu türe özel eksiksiz bir sınıf tanımı oluşturur.
Sınıf şablonları birden fazla tür parametresine ve hatta tamsayı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 değerinden oluşan dizi
arr[0] = 3.14;Üye işlevlerini sınıfın dışında tanımlarken şablon bildirimini yinelemelisin:
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++'ta genel programlamanın temelini oluşturur ve her türle çalışan yeniden kullanılabilir veri yapıları yazmanı sağlar.
Görev
KolaySınıf şablonlarını kullanarak her tür veriyi tutabilen esnek bir kapsayıcı oluşturmak için genel amaçlı bir depolama sistemi kuralım. Ş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: Basit bir kapsayıcı olarak işlev gören ve tek bir değeri bazı kullanışlı işlemlerle birlikte tutanStorageadlı bir sınıf şablonu tanımlayın:Storageşablonunuz şunları içermelidir:- Saklanan değeri tutacak özel bir üye
- Başlangıç değeri alan bir kurucu
- Saklanan değeri döndüren bir
getValue()yöntemi - Saklanan değeri güncelleyen bir
setValue()yöntemi - Değer, T türünün varsayılan oluşturulmuş değerine eşitse
true, aksi takdirdefalsedöndüren birisEmpty()yöntemi
Ayrıca, birbiriyle ilişkili iki değeri tutan ve iki tür parametresi alan
Pairadlı bir sınıf şablonu oluşturun:- Birinci ve ikinci değerler için özel üyeler (farklı türlerde olabilirler)
- Her iki değeri de başlatan bir kurucu
- Her bir değeri almak için
getFirst()vegetSecond()yöntemleri (<first>, <second>)yazdıran birdisplay()yöntemi
main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):- Bir tamsayı değeri
- Yeni bir tamsayı değeri
- Bir dizge değeri
- Bir double değeri
Şablonlarınızı şu şekilde gösterin:
- İlk tamsayıyla bir
Storage<int>oluşturupInt storage: <value>yazdırın setValue()kullanarak ikinci tamsayıyla güncelleyin, ardındanUpdated: <value>yazdırın- Dizge girdisiyle bir
Storage<std::string>oluşturupString storage: <value>yazdırın - Dizge depolamasının boş olup olmadığını kontrol edip
Is empty: <true/false>yazdırın (trueveyafalseyazdırın) - Dizge ve double değerleriyle bir
Pair<std::string, double>oluşturup ardındandisplay()çağırın - Her iki tamsayı girdisiyle bir
Pair<int, int>oluşturup ardındandisplay()çağırın
Örneğin, girdiler 42, 100, Hello ve 3.14 olduğunda:
Int storage: 42
Updated: 100
String storage: Hello
Is empty: false
(Hello, 3.14)
(42, 100)Aynı Storage şablonunun tamsayılarla ve dizgelerle sorunsuz çalıştığına, Pair şablonunun ise farklı türleri bir araya getirebildiğine dikkat edin. Derleyici, kullandığınız her tür birleşimi için ayrı sınıf tanımları oluşturur. Tek türlü şablonlar için template <typename T> söz dizimini, birden fazla tür parametresi olan şablonlar içinse template <typename T, typename U> söz dizimini kullanmayı unutmayın.
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ıyla Storage<int> oluştur ve yazdır: Int storage: <value>
// TODO: setValue() kullanarak ikinci tam sayıyla güncelle ve yazdır: Updated: <value>
// TODO: String girdisiyle Storage<std::string> oluştur ve yazdır: String storage: <value>
// TODO: String depolama alanının boş olup olmadığını kontrol et ve yazdır: Is empty: true/false
// TODO: String ve double ile Pair<std::string, double> oluştur, display() çağır
// TODO: İki tam sayıyla Pair<int, int> oluştur, display() ç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 KonteynerKendi başına pratik yap: Online C++ derleyicisi