C++11 – Üye fonksiyonlarda ‘default’ ve ‘delete’ manipülasyonu

C++03 standartlarına göre boş bir sınıf tanımlasanız bile derleyici tarafından bir tane default constructor, copy ctor(constructor) ve atama operatörünü (operator=) sizin için oluşturuyordu.

C++11 standartlarıyla beraber direkt olarak derleyicinin bu tarz davranşlarını manipüle etme şansına hakim oluyorsunuz. C++ programlama dilini işte en çok bu yüzden seviyorum, yazılımcıya olabildiğince fazla hareket alanı sağlıyor.

Tipik bir örnek olarak eğer sınıfınıza herhangi bir ctor tanımladığınızda derleyici sizin için ctor tanımlamayacaktır. Aşağıdaki kodu inceleyelim;


#include <iostream>

using namespace std;

class herbibk
{
public:
    herbibk(int a) {};
};

int main(int argc, char**argv)
{

    herbibk hbk(5); //ok
    herbibk hb; //hata derleyici default ctor oluşturmadığı için:
                      //main.cpp:23:13: error: no matching function for call to ‘herbibk::herbibk()’

    return 0;
}

C++11 ile gelen yeni özellikle beraber derleyiciye kardeşim sen yine bana default ctor üret diyebiliyoruz;

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5); //ok    
    herbibk hb; //ok
    

 
    return 0;
}

Görüldüğü üzere artık derlerken hata almıyoruz.

herbibk()  = default;

İfadesini sadece sınıfın tanımına ekleyerek derleyici tarafından oluşturulan default ctor’un her zaman oluşturulmasını sağladık.

Başka bir kullanımı ise, daha önce C++03 zamanıda : ) bir sınıfı kopyalanamaz yapmak için copy ctor’unu ve atama operatörünü private yapılırdı. Şimdi bizim ‘delete’ imiz var hatta operator new’ i de ‘delete’ edebiliriz, Şöyle ki;

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
    herbibk(const herbibk&) = delete;
    herbibk& operator=(const herbibk&) = delete; 
    void* operator new(std::size_t) = delete;
    void* operator new[](std::size_t) = delete; 
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5); //ok    
    herbibk hb(hbk); //hata  derleyiciye copy ctor fonksiyonunu oluşturma demiştik : main.cpp:21:19: error: use of deleted function ‘herbibk::herbibk(const herbibk&)’
    
    hb = hbk; // hata derleyiciye atama operatörü fonksiyonunu oluşturma demiştik 🙂  : main.cpp:23:8: error: use of deleted function ‘herbibk& herbibk::operator=(const herbibk&)’
    
    herbibk *pHbk = new herbibk[4]; // hata main.cpp:25:34: error: use of deleted function ‘static void* herbibk::operator new [](std::size_t)’
    herbibk *pHbk = new herbibk; // hata main.cpp:26:25: error: use of deleted function ‘static void* herbibk::operator new(std::size_t)’

    return 0;
}

‘delete’ anahtar kelimesi otomatik tür dönüşümünü engellemek amacıyla tüm üye fonksiyonlara uygulanabilir, Örneğin;

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
    herbibk(const herbibk&) = delete;
    herbibk& operator=(const herbibk&) = delete;
    void f(int a) {};
    void f(double &) = delete;
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5); //ok    
    herbibk hb;
    
    hb.f(5); // ok sorun yok
    hb.f(5.); // ok sorun yok, çünkü otomatik olarak 5.0 int türüne dönüştürüldü.
    
    return 0;
}

Ayrıca bu kullanımı fonksiyon şablonlarını (function template) kullanarak genelleştirebiliriz; Örneğin f fonksiyonunu integer türü haricindeki hiçbir argümanla çağıramayalım:

#include <iostream>

 
using namespace std;
 
class herbibk
{
public:
    herbibk(int a) {};
    herbibk()  = default;
    herbibk(const herbibk&) = delete;
    herbibk& operator=(const herbibk&) = delete;
    void f(int a) {};
    template<typename T> void f(T) = delete;
};
 
int main(int argc, char**argv) 
{
 
    herbibk hbk(5);  
    herbibk hb;
    
    hb.f(5); // ok sorun yok 
    hb.f(5.00); // hata: main.cpp:26:14: error: use of deleted function ‘void herbibk::f(T) [with T = double]’
    
    return 0;
}