2012-03-28 19 views
62

Aşağıdaki kodda, neden daughter türünde bir nesneyi yerleştirdiğimde, varsayılan grandmother() yapıcısının çağrıldığını anlamıyorum.Varsayılan yapıcı neden sanal devralma olarak adlandırılıyor?

grandmother(int) yapıcısını çağırmam gerektiğini (mother sınıf yapıcımın belirtimini izlemek için) veya bu kod sanal devralma nedeniyle derlenmemelidir.

Burada derleyici, arka tarafımda grandmother varsayılan yapıcıyı sessizce çağırırken, hiç istemedim.

#include <iostream> 

class grandmother { 
public: 
    grandmother() { 
     std::cout << "grandmother (default)" << std::endl; 
    } 
    grandmother(int attr) { 
     std::cout << "grandmother: " << attr << std::endl; 
    } 
}; 

class mother: virtual public grandmother { 
public: 
    mother(int attr) : grandmother(attr) { 
     std::cout << "mother: " << attr << std::endl; 
    } 
}; 

class daughter: virtual public mother { 
public: 
    daughter(int attr) : mother(attr) { 
     std::cout << "daughter: " << attr << std::endl; 
    } 
}; 

int main() { 
    daughter x(0); 
} 
+0

Ne derleyici (ve sürümü)? Hangi argümanlarla derledin? Fedora üzerinde – orlp

+0

gcc 4.6.3 20120306 (Red Hat 4.6.3-2) 15. Argümanlar şunlardır: -O0 -g3 -Wall -c -fmessage-length = 0 –

+0

g ++ 4.1.2 aynı soruna sahiptir: http: // codepad.org/L0jBXfSP – orlp

cevap

66

sanal devralma kullanarak, sanal temel sınıf yapıcı, doğrudan en türetilen sınıfın kurucusu tarafından kullanılır. Bu durumda, daughter yapıcısı doğrudan grandmother yapıcısını çağırır.

Başlatma listesinde grandmother yapıcısını açıkça aramadığınızdan, varsayılan kurucu çağrılacaktır. Doğru kurucusunu çağırmak için, değiştirin:

daugther(int attr) : grandmother(attr), mother(attr) { ... } 

da This FAQ entry bakınız.

+2

Bu tamamen mantıklı, teşekkürler! Hiyerarşideki tüm kurucular, kendi sınıflarına göre değil, son sınıftan çağrılır. Bunu hiç düşünmemiştim. C++ spec bazen zor olabilir ... –

+0

Teşekkür ederim! Dolayısıyla sanal miras durumunda, yapılacak en iyi şey zincirin tüm kurucularını manuel olarak aramaktır. –

+0

Mükemmel cevap! Teşekkürler! –