2010-01-31 27 views
19

"Sanal bir işlevin içinde bildirilen bir sınıf için sanal bir tablo var" yazan birçok insan okurum.Sanal Tablo C++

Sorum şu ki, sanal bir işlevi olan veya o sınıftan türetilen sınıflar için de geçerli olan bir sınıf için geçerli bir vtable var.

örneğin

class Base{ 
    public: 
     virtual void print(){cout<<"Base Print\n";} 
}; 
class Derived:public Base{ 
    public: 
     void print(){cout<<"Derived print\n";} 
}; 

//From main.cpp 
Base* b = new Derived; 
b->print(); 

Soru: Sonra çıkış olmazdı "türetilmiş baskı" türetilmiş sınıf için hiçbir vtable orada olsaydı. Dolayısıyla IMO, sanal işlevi bildirilen herhangi bir sınıf için ve aynı zamanda bu sınıftan miras kalan sınıflar için bir vtable var. Bu doğru mu ?

+2

Denemeyi tamamlamak için, türetilmiş ve aynı zamanda geçersiz kılmayı geçersiz kılan sınıf türetilmiş2 oluşturun. Böyle bir örnek üzerinde bir işaretçi tabanını temel almak için çağrı yapın ... – VoidPointer

+2

Daha fazla bilgi Vtable @ aşağıdaki Link hakkında: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/ –

cevap

19

Bildiğim kadarıyla sadece sanal fonksiyonlu özgü işlevsellik vtable ayrı bir sürümünü gerekir uygulanması türetilmiş sınıf VTABLE için geleneksel bir yaklaşımla, kabul edilir türetilmiş sınıftan en az bir sanal işlevi geçersiz kılarsa ve yalnızca ise. Örneğinizde, Derived, sanal işlevi print geçersiz kılar. Derived'un kendi sürümü print olduğundan, Derived vtable'daki ilgili giriş Base vtable'daki değerden farklıdır. Bu normalde Derived için ayrı bir vtable gerektirir.

Derived ise hiç bir şey geçersiz vermedi resmen hala ayrı polimorfik sınıf olacaktır, ama onun sanal fonksiyonları yanı Derived düzgün biz sadece yeniden olabilirdi Base VTABLE çalışması yapmak üzere. Yani, teknik olarak Derived için ayrı bir vtable gerek yoktur. Bununla birlikte, pratik uygulamalarda, genellikle "vtable" olarak adlandıracağımız veri yapısı, genellikle bazı ek sınıfa özgü bilgileri de tutar. Bu ekstra bilgi o kadar sınıfa özgüdür ki, çoğu zaman, aynı sanal işlevler kümesini kullansalar bile, hiyerarşide farklı sınıflar arasında veterinerler paylaşmak imkansız hale gelir. Örneğin, bazı uygulamalarda, her bir polimorfik nesnede saklanan vtable işaretleyici, sınıf hakkında "RTTI bilgisi" olarak da bilinen veri yapısını işaret eder.Bu nedenle, çoğu (eğer olmasa da) pratik uygulamalarda, her bir polimorfik sınıf, bu tablolarda saklanan sanal işlev işaretçileri aynı olsa bile kendi vtable'ını alır.

+1

@AndreyT: Yeni başlayanlar için iyi bir şekilde C++ ile ilgili kavramları açıklayan bazı web sayfalarını biliyor musunuz? Bir vtable'ın neden gerekli olduğunu ve tam olarak nasıl uygulandığını anlamaya çalışıyorum. – Lazer

+0

@Lazer uygulama detayları belirtilmemiş. Tablo, çalışma zamanında sistemin polimorfik fonksiyonun hangi sürümünün çağrılacağını bilmesi gerekir (bu, derleme zamanında belirlenemez; bir taban sınıfı işaretçisinde bir işlemi düşünür) - işaretçi bir örneğe işaret ederse işlem farklı olabilir türetilmiş sınıf veya temel sınıfın örneği). Https://en.wikipedia.org/wiki/Virtual_method_table adresine bakın. – RJFalconer

2

Evet, bu doğru. Bir sınıf, tüm veri üyelerini vtable dahil olmak üzere temel sınıfından devralır. Bununla birlikte, vtable girdileri buna göre ayarlanır (örneğin sınıf bir temel sınıf sanal yöntemini geçersiz kılarsa, vtable'daki karşılık gelen girdinin kendi uygulamasına işaret etmesi gerekir). Ancak, "vtable" kavramının, her derleyicinin her derleyici tarafından yaygın olarak kullanıldığı yaygın bir uygulama olduğunu aklınızdan çıkarmayın, ancak zorunlu veya standartlaştırılmış değildir.

+0

vtable olduğunu Üye veya üye gibi bir şey değil. Vptr mi demek istiyorsun? – curiousguy

3

Evet, anlayışınız doğru. Herhangi bir sanal işlevi olan bir tabana sahip herhangi bir sınıf bir vtable vardır.

3

Evet, doğru. Zaten tabanında sanal olarak baskı tanımlanan çünkü ...

class derived:public base{ 
public: 
virtual void print(){cout<<"derived print\n";} 
}; 

: Aslında, verilen üssün Definition:

class derived:public base{ 
public: 
void print(){cout<<"derived print\n";} 
}; 

tamamen eşdeğerdir.

Ben derleyici o zorlamak isterdim ki ...

İlgili konular