C++ dilinde, 'sanal yapıcı' kavramı tam anlamıyla yoktur. Ancak, nesne türevlerinin örneklerini yalnızca çalışma zamanında bilinen türler için oluşturmak gerekliliği sıkça karşılaşılmaktadır. Tarihsel olarak, bu tür bir görev, sanal fonksiyonlar - genellikle 'clone()' veya 'create()' - aracılığıyla "sanal yapıcı" deseni ile çözülmektedir.
Meselenin Tarihçesi: C++'da, erken sürümlerden itibaren, yapıcıların sanal olarak tanımlanamayacağı kısıtlaması ile karşılaşılmıştır. Bununla birlikte, bazen sınıf hiyerarşilerinde, yalnızca çalışma zamanında bilinen bir türden yola çıkarak yeni nesneler oluşturma ihtiyacı ortaya çıkmaktadır.
Sorun: Klasik olarak, yapıcılar sanal fonksiyon mekanizmalarına tabi değildir; çağırma her zaman derleme aşamasında çözülmektedir. Bu, temel sınıfın yapıcıları aracılığıyla gerçek çalışma zamanı türü ile nesne üreten "canlı" bir fabrika elde etmeyi engellemektedir.
Çözüm: Temel sınıfta bir sanal fonksiyon uygulanması önerilir - genellikle bu 'clone()' (nesne kopyalama) veya 'create()' (durumu kopyalamadan aynı türde nesne oluşturma) olmaktadır.
Kod örneği:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived : public Base { public: Derived(int v) : value(v) {} Base* clone() const override { return new Derived(*this); } private: int value; }; void process(const Base& b) { Base* b2 = b.clone(); // Sanal yöntem aracılığıyla doğru kopyayı oluşturun delete b2; }
Anahtar Özellikler:
C++'da yapıcılar virtual olarak tanımlanabilir mi?
Hayır, C++ söz dizimi yapıcı için virtual belirleyicisini desteklemez. Aksi takdirde, derleyici bir derleme hatası verir.
Eğer clone() yöntemini kendiniz tanımlarsanız, temel sınıfta onu tam sanal (pure virtual) yapmak zorunlu mu?
Hayır, zorunlu değildir. clone() için varsayılan bir uygulama verebiliriz, örneğin yalnızca belirli bir durumu kopyalamanın mantıklı olduğu durumlarda veya nullptr döndürebiliriz, ancak genellikle daha fazla kontrol için tam sanal bir fonksiyon olarak yapılır.
Fabrika statik yöntemlerini clone() yerine kullanmak mümkün mü? Bu sanallık ile nasıl ilişkilidir?
Statik fabrika yöntemleri sanal değildir ve klasik mekanizmada mirasçılar içinde geçersiz kılınamaz. Gerçek bir "sanal yapıcı" için bir örnek sanal fonksiyonu ya da başka bir tür dinamik çözümleme yöntemi gereklidir.
Geliştirici deseni statik bir yöntemle gerçekleştirmiş:
class Base { public: static Base* create() { return new Base; } }; class Derived : public Base {}; // ... Base::create() çağrılır, Base döndürür, gerçek tür bilgisi kaybolur
Artıları:
Eksileri:
Kod clone() kullanıyor:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived : public Base { int x; public: Derived(int x) : x(x) {} Base* clone() const override { return new Derived(*this); } };
Artıları:
Eksileri: