12 Mart 2018 Pazartesi

C++ ile Constructor

buit-in tiplerin constructor metodu yoktur
C++'ta built-in tiplerin constructor metodları yoktur.
int a = 42 ve
int a;
a = 42 aynı şeydir. a tipinin constructor metodu olmadığı için a tipini tanımlayan ilk cümle bir şey çalıştırmaz.

constructor'dan virtual metod çağrılmaz
Genel kural olarak bir sınıfın contructor veya destructor metodlarında virtual metodlar çağrılmaz. 
Bu kural çağrılamaz demiyor, çağrılmasa daha iyi diyor. Standart  bu kuralı şöyle açıklıyor.
Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class’s non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class. If the virtual function call uses an explicit class member access (5.2.5) and the object expression refers to the complete object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the behavior is undefined. 
Constructor için virtual metod çağrısına parasoft şu uyarıyı verir.
"A class's virtual functions shall not be invoked from its destructor or any of its constructors (JSF-71.1-2)"
Eğer derleyicimiz durumu yakalarsa şu hatayı verir.
pure virtual ‘virtual int X::f()’ called from constructor
Bu kural Java için, geçerli olmasa da hataya açık kapı bıraktığı için, yapılmaması bence daha iyi. Örnek de hatalı durum görülebilir.

Örnek
virtual metod çağrılarının, kalıtım yapan sınıfları değil, kendisini veya alt sınıfı tetiklediği görülebilir.
struct V {
  virtual void f();
  virtual void g();
};
struct A : virtual V {
  virtual void f();
};
struct B : virtual V {
  virtual void g();
  B(V*, A*);
};
struct D : A, B {
  virtual void f();
  virtual void g();
  D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
  f(); // calls V::f, not A::f
  g(); // calls B::g, not D::g
  v->g(); // v is base of B, the call is well-defined, calls B::g
  a->f(); // undefined behavior, a’s type not a base of B
}
Örnek
Şu kod yanlış. Pure virtual bir metod çağrıldığı için uygulama çöker.
struct Base
{
    Base() { method(); }

    virtual void method() = 0;
};

struct Derived : Base
{
    void method() {};
};

int main()
{
    Derived d;
}
Örnek
Şu kod pure virtual metodu dolaylı çağırdığı için yanlış.
#include <iostream>

struct X {
    virtual void foo() = 0;
    void bar() { foo(); }
    X() { bar(); std::cout << "X"; }
};

struct Y : X {
    void foo() override {}
};


int main() {
    Y y;
    return 0;
}

constructor'ın adresi alınamaz
constructor ve destructor metodlarının adresleri alınamaz.
"References and pointers cannot be used on constructors and destructors because their addresses cannot be taken."
Örnek
Şöyle yaparız.

class Sample{
    private: int x;
    public: Sample() { x = 100; };
    public: void* member() { x = 200; };
};

template <class X>
void call_me(Sample s, X function){
    (s.*function)();
};

call_me(s, &Sample::member);   //valid
call_me(s, &Sample::Sample);   //invalid
call_me(s, &Sample::~Sample);  //invalid
Adresinin alınamamasındaki mantık, constructor'ın function pointer haline getirilmesinde bir fayda olmaması. Çünkü her constructor farklı bir imzaya sahip şeklinde açıklanmış.
ilklendirme sırası
Sınıfın değişkenleri constructor'da deklare edildikleri sırada ilklendirilirler. Eğer constructor içinde deklare edildikler sırada kullanılmazlarsa gcc aşağıdakine benzer bir hata verir.
Field1 will be initialized after Field2.

Örnek
Elimizde şöyle bir kod olsun. mSpeed mEntity'den daha önce ilklendirilir.
class Foo {
public:
    Foo(int speed) :
        mSpeed(speed),
        mEntity(speed)
    { }

private:
    int mSpeed;
    Entity mEntity;
}
delegating constructor
C++11 ile Delegating Constructor yazısına taşıdım.

constructor inheritance
C++11 ile Constructor Inheritance yazısına taşıdım.

constructor içinde exception
Constructor İçinde Exception Fırlatmak yazısına taşıdım.

constructor initializer list içinde exception
Ata sınıftan veya member variable'dan kaynaklanan exception'ı durdurmanın yolu yoktur.
#include <iostream>
using namespace std;
class A{
public:
    A() try : i{ 0 }{ throw 5; }
    catch (...){ cout << "Exception" << endl; }
private:
    int i;
};


int main(){
    A obj;
}




Hiç yorum yok:

Yorum Gönder