Virtual Table - VTable
C++ standardı polymorphism'in (çok biçimlilik) nasıl gerçekleşeceğini tanımlamaz. Ancak tüm derleyiciler vtable yöntemini kullanıyorlar. Bir gün başka bir üretici yeni bir yöntemle karşımıza çıkabilir.
Virtual metodlar derleyicinin sınıf için vtable üretmesine sebep olur. VTable bilgisinin nerede saklanacağı standart tarafından belirlenmiyor.
Microsoft derleyicisi şu şekilde saklıyor. Elimizde şöyle bir kod olsun.
De-Virtualization
Metodun virtual olmasına rağmen, derleyici tarafında vtable kullanılmasına gerek olmadığının tespit edilmesi ve verimlilik adına direkt çağrı haline getirilmesidir. Açıklaması şöyle
Virtual Metodların Access Modifier Değiştirmesi
Ata sınıfta public olan bir virtual metodun, kalıtan sınıfta private yapılması. Bu kullanım şeklini hiç sevmiyorum ama bazı insanlar inatla kullanıyorlar. Şöyle yapılır
Pure Virtual
Diğer programlama dillerinde abstract diye bir anahtar kelime ile metodun pure virtual olduğu belirtilir. C++'ta şöyle belirtilir.
Ata Sınıfta Pure Virtual Olmayan Bir Metod Sonradan Pure Virtual Yapılabilir
Saçma ama yine de yapılabiliyor. B metodu ilk ata sınıfımız. Bundan D kalıtır ve foo() metodunu pure virtual hale getirir. Böylece D'den kalıtan G foo() metodunu override etmek zorunda kalır.
C++ standardı polymorphism'in (çok biçimlilik) nasıl gerçekleşeceğini tanımlamaz. Ancak tüm derleyiciler vtable yöntemini kullanıyorlar. Bir gün başka bir üretici yeni bir yöntemle karşımıza çıkabilir.
Virtual metodlar derleyicinin sınıf için vtable üretmesine sebep olur. VTable bilgisinin nerede saklanacağı standart tarafından belirlenmiyor.
Microsoft derleyicisi şu şekilde saklıyor. Elimizde şöyle bir kod olsun.
class A {
virtual Ax() {}
int a, b;
};
class B {
virtual Bx() {}
int c, d;
};
class C : public A, public B {
int foo, bar;
};
Object yerleşimi şöyledir.A's VTable ptr
A's member variables.
B's Vtable ptr
B's member variables.
C's member variables.
Gcc ise vtable bilgisini object'in en sonuna yerleştirir.De-Virtualization
Metodun virtual olmasına rağmen, derleyici tarafında vtable kullanılmasına gerek olmadığının tespit edilmesi ve verimlilik adına direkt çağrı haline getirilmesidir. Açıklaması şöyle
If the compiler can detect at compile-time that a particular call to a virtual member function, through a polymorphic type, will undeniably call a specific version of that function, then it is allowed avoid using the virtual dispatching logic, calling the function statically. That's behaving "as if" it had used the virtual dispatching logic, since the compiler can prove that this is the function that would have been called.
As such, the standard does not define when de-virtualization is allowed/forbidden....
Virtual Metodların Access Modifier Değiştirmesi
Ata sınıfta public olan bir virtual metodun, kalıtan sınıfta private yapılması. Bu kullanım şeklini hiç sevmiyorum ama bazı insanlar inatla kullanıyorlar. Şöyle yapılır
#include <iostream>
class A {
public:
virtual void f() { std::cout << "virtual_function"; }
};
class B : public A {
private:
void f() { std::cout << "private_function"; }
};
void C(A &g) { g.f(); }
int main() {
B b;
C(b);
}
Bir başka örnekstruct A {
A(){ }
virtual ~A(){ }
A(A&&){ }
public:
virtual void bar(){ std::cout << "A" << std::endl; }
};
struct B : public A{
private:
virtual void bar(){ std::cout << "B" << std::endl; }
};
int main()
{
A *a = new B;
a -> bar(); //prints B
}
Java virtual bir metodun access modifier değiştirmesine izin vermiyor ve bence çok ta iyi yapıyor.public class A{
public void foo(){ }
}
public class B extends A{
@Override
private void foo(){ } //compile-error
}
Pure Virtual
Diğer programlama dillerinde abstract diye bir anahtar kelime ile metodun pure virtual olduğu belirtilir. C++'ta şöyle belirtilir.
virtual void MyFunction() = 0;
Aslında şöyle de yapılabilirdir.pure virtual void MyFunction();
Sebebibini Bjarne Stroustrup şöyle açıklamış.Yani tartışmalar daha fazla uzamasın istemiş.The curious= 0
syntax was chosen over the obvious alternative of introducing a new keywordpure
orabstract
because at the time I saw no chance of getting a new keyword accepted. Had I suggestedpure
, Release 2.0 would have shipped without abstract classes. Given a choice between a nicer syntax and abstract classes, I chose abstract classes. Rather than risking delay and incurring the certain fights overpure
, I used the tradition C and C++ convention of using 0 to represent not there.
Ata Sınıfta Pure Virtual Olmayan Bir Metod Sonradan Pure Virtual Yapılabilir
Saçma ama yine de yapılabiliyor. B metodu ilk ata sınıfımız. Bundan D kalıtır ve foo() metodunu pure virtual hale getirir. Böylece D'den kalıtan G foo() metodunu override etmek zorunda kalır.
class B // from a third party
{
public:
virtual void foo();
};
class D : public B
{
public:
void foo() override = 0; // allowed by gcc 4.8.2
virtual void bar() = 0;
};
class G : public D
{
public:
// forgot to reimplement foo
void bar() override;
};
int main()
{
G test; // compiler error is desired
}
Hiç yorum yok:
Yorum Gönder