2011-05-03 29 views
8

İlginç bir birden fazla miras sorunu çözmeyi deniyorum.C++ Çoklu Kalıtım - neden çalışmıyorsunuz?

class A 
{ 
public: 
    virtual int foo() = 0; 
    virtual int bar() = 0; 
}; 

Sonra, kısmen bu arayüzü tamamlamaktadırlar soyut sınıflar bulunmaktadır:

grandparent birden fazla yöntem ile bir ara-yüz sınıfıdır.

class B : public A 
{ 
public: 
    int foo() { return 0;} 
}; 

class C : public A 
{ 
public: 
    int bar() { return 1;} 
}; 

Ben ebeveynlerin hem devralır kullanmak istiyorum ve sınıf yöntemi kullanarak direktifler vasıtasıyla nereden geliyor gerektiğini belirtir: Bir DI çalıştıkları için hataları olsun örneğini deneyin

class D : public B, public C 
{ 
public: 
    using B::foo; 
    using C::bar; 
}; 

soyut bir sınıf oluşturur.

int main() 
{ 
    D d; //<-- Error cannot instantiate abstract class. 

    int test = d.foo(); 
    int test2 = d.bar(); 

    return 0; 
} 

Sorunları ve kısmi uygulamaları nasıl en iyi şekilde kullanabileceğimi anlamama yardımcı olan biri var mı?

+2

Bir elmas deseninde sanal devralmayı kullanmanız gerekir. Ama ben senin sorununun kendiliğinden çözüleceğine inanmıyorum. – David

cevap

13

Elmas mirasınız yok. B ve ve C temel sınıflarının her birinin temel sınıfları, A'dan neredeyse devralmadıkları için kendi A taban sınıfının alt nesnesine sahiptir. C den A::foo ve A::barB gelen ve A::foo ve A::bar:

Yani, D yılında, gerçekten uygulanması gereken dört saf sanal üye işlevleri vardır.

Muhtemelen sanal devralmayı kullanmak istersiniz. sınıf bildirimleri ve baz sınıf listeleri şöyle görünecektir:

class A 
class B : public virtual A 
class C : public virtual A 
class D : public B, public C 

o zaman D diğer iki saf sanal fonksiyonlar geçersiz kılmak gerek sanal miras kullanmayı istemiyorsanız:

class D : public B, public C 
{ 
public: 
    using B::foo; 
    using C::bar; 

    int B::bar() { return 0; } 
    int C::foo() { return 0; } 
}; 
-2

Düzgün miras almaları için temel sınıflarınızı virtual yapmalısınız. Genel kural, özel üye olmayan tüm işlevlerin ve temel sınıfların, virtual UNLESS olması ve ne yaptığınızı bilmeniz ve bu üye/taban için normal devralmayı devre dışı bırakmasıdır.

+1

"Genel kural, tüm genel üye işlevleri ve temel sınıfların sanal olması gerektiğidir" Ne? Bu kimin genel kuralı? Eğer bir şey varsa, sanal üye fonksiyonlarıyla ilgili genel kural, onları özel kılmak ve temel sınıfta bir kamu-dışı üye fonksiyonuna sahip olmak özel sanal üye fonksiyonunu çağırmaktır (bu, GotW makalesinde ["Sanallık"] (http: // www.gotw.ca/publications/mill18.htm)). Sanal temel sınıflara gelince ... Son birkaç yılda sanal miras kullanmam gerektiğini düşündüğüm bir vakayı düşünebilirim. –

+0

@JamesMcNellis "_I son birkaç yıl içinde sanal inheritance kullanmak için ihtiyacım olan sadece bir örneği düşünebilirim." ** ** ** olmayan sanal mirasın kaç kere kullanıldığını? – curiousguy

+0

@JamesMcNellis: Bu makale çoğunlukla toplam BS'dir. Doğru olan tek şey hakkında çoğu üye fonksiyonunun (sanal ya da değil) özel olması gerektiğidir. Kamusal olmayan sanal üye işlevlerine sahip olmak, gerçekleşmesini bekleyen bir felakettir ve temel olarak sınıfın alt sınıflara ayrılmayacağı anlamına gelir. –