7 Mayıs 2018 Pazartesi

C++11 ile Constructor Inheritance

Giriş
using kelimesi birçok faklı amaç için kullanılabiliyor. C++11 ile gelen yeniliklerden bir tanesi ata sınıftaki erişimimiz olmayan metodları erişilebilir hale getirmesi. Bu konu için using kelimesi yazısına bakabilirsiniz.

Bir diğer kullanım yeri ise ata sınıftaki constructor'ı kendi sınıfımızın içine alması.

Constructor inheritance Java, C# gibi dillerde bile olmayan bir özellik.  Açıklaması şöyle
If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using Base::Base;), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.
Eğer aynı imzalı constructor sağlarsak ata sınıftaki constructor gizlenir. Açıklaması şöyle. Dolayısıyla bizi bu dertten de kurtarıyor.
As with using-declarations for any other non-static member functions, if an inherited constructor matches the signature of one of the constructors of Derived, it is hidden from lookup by the version found in Derived.
Örnek
Eskiden ata sınıfın bir constructor metodunu kalıtan sınıfta da yazmak gerekiyordu.
class Base {
public:
  int i;
  Base(int x): i(x) {}
};

class Derived : private Base {
public:
  Derived(int x) : Base(x) {}
};
Şimdi artık using Base::Base yapmamız yeterli. Şöyle yaparız.
class Base {
public:
  int i;
  Base(int x): i(x) {}
};

class Derived : private Base {
public:
    using Base::Base;
};
Örnek
Şöyle yaparız.
class Foo : public Base {
public:
  using Base::Base;

  // My subclass specific code
};
Ata Sınıfın Constructor Erişimini Değiştirmek
Ata sınıfın constructor metodu public ise bunu sonradan private yapmak mümkün değil.

Örnek
Elimizde şöyle bir kod olsun.  Ata sınıfın constructor metodu private yapılamaz.
#include <vector>

template<typename T>
class Vec : std::vector<T>
{
private:
    using std::vector<T>::vector;       // Works, even if private. Why?
public:
    using std::vector<T>::operator[];   // must be public
};

int main(){
    Vec<int> vec = {2, 2};
    auto test = vec[1];
}
Parametrelere Erişim 
Ata sınıfın constructor metoduna geçilen parametrelere erişim artık mümkün değil. Elimizde Base sınıfı olsun ve bu sınıfın int alan bir constructor metodu olsun.
class Base {
  int y;
public:
  Base (int a) : y(a)  {}
};
Kalıtan sınıfın int a parametresine erişimi artık mümkün değil.
class Derived : public Base
{
    public:
    using Base::Base;
    float z {a}; //Bu olmuyor
};
Ancak şöyle yapılabilir.
class B : public A
{
  int z {y}; //Bu olur
public:
  using A::A;
};
Her Türlü Constructor Inherit Edilebilir mi ?
Constructor inheritance, parameterless constructor veya copy constructor için kullanılamaz.
For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the complete class where the using-declaration appears or the constructor would be a default, copy, or move constructor for that class.
Dolayısıyla aşağıdaki kod derlenmez
class C {
public:
    C(int) {}
    C(const C&) {}
    C() {}
};  

class D : public C { 
public:
    using C::C;
};  

int main() {
    C c;
    D d_from_c(c); // does not compile, copy ctor is not inherited
    D d_from_int(1); // compiles, C(int) is inherited
}   



1 yorum:

  1. Merhaba uzun süredir sizi takip ediyorum. Bu blog'u çok seviyorum, çok başarılı lütfen yazılarınıza devam edin.

    Yalnız blog'da eksiğini hissettiğim bir şey var. Acaba arama kutusu koyarsanız daha iyi olmaz mı ? Çünkü bir sürü kategori içerisinde aranılanı bulmak pek kolay olmuyor, arama kutusuyla istediğimize direkt ulaşabiliriz diye düşünüyorum.

    İyi çalışmalar.

    YanıtlaSil