3

Considérez l'architecture suivante:C++ héritage multiple de diamants et pures fonctions virtuelles

class A //abstract interface 
{ 
    public: 
    virtual void f() = 0; 
}; 
class AA : public A //abstract interface 
{ 
    public: 
    virtual void g() = 0; 
}; 
class AAA : public AA //abstract interface 
{ 
    public: 
    virtual void h() = 0; 
}; 

class B : public A // implementation class 
{ 
    public: 
    void f() override {}; 
}; 
class BB : public B, public AA {}; // implementation class 
{ 
    public: 
    void g() override {}; 
}; 
class BBB : public BB, public AAA {}; // implementation class 
{ 
    public: 
    void h() override {}; 
}; 

En tant que tel, BB et BBB sont des classes virtuelles, parce que f n'est pas remplacée par BB, ni f, ni g sont par BBB. Mon souhait est de pouvoir instancier BB et BBB (de sorte que BB et BBB utilisent l'override de f défini par B, et BBB utilise l'override de g défini par BB).

La question est: qui les relations d'héritage devraient être marqués comme virtual instancier BB et BBB?

Le diagramme d'héritage devrait idéalement ressembler à ceci:

A 
|\ 
| \ 
| \ 
AA B 
| \ | 
| \ | 
AAA BB 
    \ | 
    \ | 
    BBB 

L'idée derrière cette conception est que A, AA et AAA sont des interfaces qui décrivent les niveaux de fonctionnalités supplémentaires. B, BB et BB sont une implémentation incrémentielle correspondante. (Ainsi que BB définit par exemple tout ce dont AA a besoin, et comporte aussi ce qu'il y a en B)

+0

Votre manque le modificateur virtuel dans vos définitions de classe, je pense, sinon tout votre question n'a pas de sens. Les détails sont importants –

+0

Bien sûr, je voulais dire le modificateur virtuel des FONCTIONS –

Répondre

1

si seulement A AA AAA sont vraiment des interfaces, je veux dire qu'ils n'ont aucun membre, alors vous n'avez pas besoin de l'héritage virtaul, implémenter uniquement des interfaces et les appeler à partir de classes de base. Ce que vous avez implémenté dans B pour l'interface A, doit également être implémenté dans BB, puis appelez B:pureVirtual() dans BB. Sinon, devrait être comme ça; (Ensuite, vous devriez jeter un oeil à: 'class1' : inherits 'class2::member' via dominance)

class A 
{ 
public: 
    virtual void f() = 0; 
}; 
class AA : virtual public A 
{ 
public: 
    virtual void g() = 0; 
}; 
class AAA : virtual public AA 
{ 
public: 
    virtual void h() = 0; 
}; 

class B : virtual public A 
{ 
public: 
    void f() override { } 
}; 
class BB : public B, virtual public AA 
{ 
public: 
    void g() override { } 
}; 
class BBB : public BB, public AAA 
{ 
public: 
    void h() override { } 
}; 

Edit: (Sans héritage virtuel)

class A //abstract interface 
{ 
public: 
    virtual void f() = 0; 
}; 
class AA : public A //abstract interface 
{ 
public: 
    virtual void g() = 0; 
}; 
class AAA : public AA //abstract interface 
{ 
public: 
    virtual void h() = 0; 
}; 

class B : public A // implementation class 
{ 
public: 
    void f() override {} 
}; 
class BB : public B, public AA // implementation class 
{ 
public: 
    void g() override {} 
    void f() override { B::f(); } 
}; 
class BBB : public BB, public AAA // implementation class 
{ 
public: 
    void h() override {} 

    void g() override { BB::g(); } 
    void f() override { BB::f(); } 
}; 
+0

Mais alors 'void g() override {BB :: g(); } 'est un remplacement de g qui appelle simplement le remplacement de BB. Ne pouvons-nous pas simplement dire que nous voulons utiliser directement la définition de g de BB? Alors que l'utilisateur implémentant BBB n'est pas tenté de trafiquer g. –

+0

@MarsyaKaustentein si vous voulez implémenter d'autres choses dans 'BBB: g()' vous le pouvez. Si vous ne voulez pas implémenter 'g() et f()' dans 'BBB', vous ne pouvez pas. Parce que ce sera alors une classe abstraite et vous ne pouvez pas avoir d'instances 'BBB'. –