11
votes

Héritage multiple sans héritage virtuel

J'essaie de comprendre plusieurs héritages, voici mon code:

struct A {
  A() {}
  static int n;
  static int increment() { return ++n; }
};
int A::n = 0;

struct B : public A {};
struct C : public A {};
struct D : public B, C {};

int main() {
  D d;
  cout<<d.increment()<<endl;
  cout<<d.increment()<<endl;
}


1 commentaires

3 Réponses :


9
votes
  1. C'est ce qu'on appelle le problème de héritage de diamant. Vous avez deux classes, qui sont dérivés de A. puis de la classe dérivée de deux. Vous avez deux versions d'incrément de vide non statique (). Avec statique, vous en avez un.
  2. Parce que vous pouvez, mais ne devez jamais remplacer la fonction non virtuelle, et votre compilateur est peut-être un mode strict ou en mode strict.

    Héritage de diamant: http://www.parashift.com/c++-faq /midiamond.html Fonctions de masquage: http://www.parashift.com/c++-faq/ cache-hérité-hérité-public.html


0 commentaires

10
votes

qu'est-ce que la moyenne ambiguë?

Un compilateur se plaint d'appels ambigus lorsqu'il ne peut pas décider quelle fonction d'appel compte tenu du contexte. Ainsi, pour comprendre les plaintes, vous devez vérifier quelles pourraient être les ambiguïtés.

Pourquoi le compilateur se plaint de l'appel ambigu de la version non statique de l'incrément (), tout en satisfaisant avec le statique?

Par définition, un Static La fonction d'une classe ne dépend pas d'une instance de la classe. Cela est souligné par le fait que vous pouvez appeler cela A :: incrément () (voir, aucune instance).

Le problème de l'héritage de diamant n'est pas que le compilateur ne sait pas quel code exécuter, c'est que cela ne sait pas quel ce à fournir (il y a deux A dans votre objet d objet, un contenu dans B et un dans c ).

Lorsque vous utilisez une fonction statique de A , aucun implicite est passé, il n'y a donc pas de problème; Si vous essayez d'utiliser une fonction STATIC statique , le compilateur ne peut pas décider si ceci doit pointer sur le A dans b < / code> ou dans C , il est ambigu.

Si j'ajoute une autre fonction d'incrément () à B ou C, le compilateur se plaindre également, même déclaré comme statique. Pourquoi?

À ce stade, le compilateur peut choisir entre B :: incrément () et c :: incrément () , lequel devrait-il choisir? C'est ambigu.

Lorsque vous avez une hiérarchie linéaire, il appelle le "plus proche" à celui-ci (qui cache ces personnes plus loin dans l'arbre d'héritage), mais ici b et c sont deux branches indépendantes et il n'y a pas de «meilleure» branche.

Remarque: même si B ne met pas en œuvre incrément , puisque A pouvez-vous appeler b :: incrément () qui appelle réellement A :: incrément () . Il en va de même pour C .


0 commentaires

2
votes

Cette instruction:

struct D : public B, C {};


0 commentaires