2017-03-11 73 views
5

Ben bu yapılara sahip C++ 11C++ çoklu kalıtım - aynı yöntem adları - bunlardan birini nasıl kaldırabilirim?

struct A { 
    int idA; 
    void setId(int i) { idA = i;} 
    int getId() { return idA;} 

    virtual void foo() = 0; 
}; 

struct B { 
    int idB; 
    void setId(int i) { idB = i;} 
    int getId() { return idB;} 

    virtual void foo2() = 0; 
}; 

struct AB : public A, public B 
{ 
    void foo() override {} 
    void foo2() override {} 
}; 

Şimdi ana içinde böyle diyebilirsiniz:

AB * ab = new AB(); 
ab->B::setId(10); 

ama gerçekten bunu sevmiyorum.

Başka bir çözüm var mı? AB numaralı telefondan struct A numaralı setId/getId numaralı yöntemlere gerek yoktur. Sadece mirasını yaptım, çünkü foo() ve A'dan diğer şeylere ihtiyacım var, ancak diğer tüm yöntemler benzersiz. Eğer A gerekmez söyledi yana

+0

Hiyerarşinizi değiştirebilir misiniz? Örneğin. A 'yi değiştirin ve ek dersler verin –

+0

@VittorioRomeo I (sınırlı bir şekilde) –

+0

"A" dan foo() 'ya da diğer şeyleri söylediğinizde, beyanlara ya da tanımlara başvuruyor musunuz? –

cevap

5

AB 'ın ad içine bu yöntemlerin ın uygulanması 'bu yöntemlerin ler versiyonunu, sen bu B koyacağız

struct AB : public A, public B 
{ 
    void foo() override {} 
    void foo2() override {} 

    using B::setId; 
    using B::getId; 
}; 

yazabilirsiniz' ve onları çağırıyor yapmak kesin.

2

Peki sarıcı yönlendirme yöntemleri:

struct AB : public A, public B 
{ 
public: 
    void setAId(int i) { A::setID(i); } 
    void setBId(int i) { B::setID(i); } 
}; 

ad gizleme "kurbanı" olmazlar Bu şekilde, niyet kodunda netleşiyor ve ne yaptıklarını yansıtan isimler var ve yapmanız Temel sınıf (lar) üyelerine açık bir şekilde erişmeye gerek yoktur.

Alternatif olarak, başka bir temel sınıf oluşturabilir ve hem A hem de setId yöntemini içerdiği B içinde sanal olarak devralabilirsiniz.

+0

Bu işe yarayacak, ancak birisi hala setId() öğesini çağırıp hatayı alabilir. –

+0

@MartinPerry Daha sonra temel sınıflarda imo korunmalıdır. – Resurrection

+0

@Ressurection Diğer sınıflar yalnızca A'dan mi yoksa yalnızca B'den miras aldığından ve bu yöntemleri çağırmak için aceleyle getirildikleri için yanlış olacaktır. –

1

Ben madeni ve kabul cevaplar hem oldukça can sıkıcı bir sorun çıkarmaktadır inanıyoruz düşünün: AB nesne

adı gizleme kullanılır
AB ab; 
A *a = &ab; 
a->setId(10); //problem 
a->foo(); //calls AB::foo() correctly 

(kabul yanıt) çağrılan asla cevabım (çağrı sarma sırasında) bunun için de geçerli değildir. Bence bu durumda doğru yaklaşım bu yüzden tek bir şey orijinal OP'ın kodundan değiştirecek, sadece foo() açığa privateA ait inehritance ve kullanmaktır:

OO ve Kalıtım ile Tipik
struct AB : private A, public B 
0

işlevselliği yeniden bilinmiyorsa O anda, onu parçalara ayırabilmenizi sağlayacak bir desen belirleyene kadar işlevi birkaç kez uygulamak daha iyidir. Örneğin, bir sınıf nesnesi bir veri taşıyıcısı olmanın ve ondan kaleme almanın yanlış olduğu hiçbir şey yoktur.

class IdentificationData { 
    int ID; 
    . . . 
} 

Ayrıca, işlevlerin bir sınıfın parçası olması gerekmez. Bir sınıf basitçe bir kaptır ve veriyi, veri üzerinde çalışabilecek fonksiyonları veya bir fonksiyon koleksiyonunu bir ortak set halinde organize etmek ve saklamak için kullanılır.

class IdentificationFunctionality{ 
    static SetID(IdentificationData* obj) {...} 
} 

Böyle yapmak, daha sonra ...

class AB: IdentificationData, B { 
    . . . 
} 

AB* ab = new AB(); 
IdentificationFunctionality::SetID(&ab); 

bu diğer faydalar, bu veri-bankacılık sisteminin ayrıntılarını bilmek gerek senin nesneler olmadan bazı Defter Tutma yapmanızı sağlayacaktır olduğunu.