Menu
CoddyTech

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.

challenge icon

Görev

Kolay

Sı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 tutan Storage adlı 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 takdirde false döndüren bir isEmpty() yöntemi

    Ayrıca, birbiriyle ilişkili iki değeri tutan ve iki tür parametresi alan Pair adlı 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() ve getSecond() yöntemleri
    • (<first>, <second>) yazdıran bir display() yöntemi
  • main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):
    1. Bir tamsayı değeri
    2. Yeni bir tamsayı değeri
    3. Bir dizge değeri
    4. Bir double değeri

    Şablonlarınızı şu şekilde gösterin:

    1. İlk tamsayıyla bir Storage<int> oluşturup Int storage: <value> yazdırın
    2. setValue() kullanarak ikinci tamsayıyla güncelleyin, ardından Updated: <value> yazdırın
    3. Dizge girdisiyle bir Storage<std::string> oluşturup String storage: <value> yazdırın
    4. Dizge depolamasının boş olup olmadığını kontrol edip Is empty: <true/false> yazdırın (true veya false yazdırın)
    5. Dizge ve double değerleriyle bir Pair<std::string, double> oluşturup ardından display() çağırın
    6. Her iki tamsayı girdisiyle bir Pair<int, int> oluşturup ardından display() ç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;
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online C++ derleyicisi