Partage de technologie

C : La différence entre composition et héritage

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Introduction à la composition et comparaison avec l'héritage

qu'est-ce que la combinaison
(1) La composition signifie utiliser des objets de plusieurs autres classes en tant que membres d'une classe.
(2) Utiliser l'arbre de classes pour expliquer les cas
(3) La combinaison est également une méthode de réutilisation de code, et son essence estStructureInclure

#include <iostream>
#include <vector>
#include <string>

// Leaf 类
class Leaf {
public:
    Leaf(const std::string& color) : color_(color) {
        std::cout << "Leaf constructor called: " << color_ << std::endl;
    }

    ~Leaf() {
        std::cout << "Leaf destructor called: " << color_ << std::endl;
    }

    void display() const {
        std::cout << "Leaf color: " << color_ << std::endl;
    }

private:
    std::string color_;
};

// Branch 类
class Branch {
public:
    Branch(int length) : length_(length) {
        std::cout << "Branch constructor called: " << length_ << " cm" << std::endl;
    }

    ~Branch() {
        std::cout << "Branch destructor called: " << length_ << " cm" << std::endl;
    }

    void display() const {
        std::cout << "Branch length: " << length_ << " cm" << std::endl;
    }

private:
    int length_;
};

// Tree 类,包含 Leaf 和 Branch 对象
class Tree {
public:
    Tree(const std::string& leafColor, int branchLength) 
        : leaf_(leafColor), branch_(branchLength) {
        std::cout << "Tree constructor called" << std::endl;
    }

    ~Tree() {
        std::cout << "Tree destructor called" << std::endl;
    }

    void display() const {
        leaf_.display();
        branch_.display();
    }

private:
    Leaf leaf_;
    Branch branch_;
};

int main() {
    Tree tree("Green", 150);
    tree.display();
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

Insérer la description de l'image ici

Comparaison des caractéristiques de l'héritage et de la composition
(1)L'héritage est une sorte de (est a) La relation est transitive et non symétrique.
(2) La combinaison est la relation d'une partie de (a un),
(3) L'héritage est une réutilisation en boîte blanche. Étant donné que l'héritage de classe nous permet de remplacer les détails d'implémentation de la classe parent en fonction de notre propre implémentation, l'implémentation de la classe parent est visible par la classe enfant.
(4) La fonctionnalité de réutilisation de la boîte blanche de l'héritage détruit dans une certaine mesure la fonctionnalité d'encapsulation de la classe, car elle exposera les détails d'implémentation de la classe parent à la sous-classe.
(5) La combinaison appartient à la réutilisation de la boîte noire.Les détails internes de l'objet contenu sont invisibles pour le monde extérieur, son encapsulation est donc relativement bonne et l'interdépendance dans la mise en œuvre est relativement faible.
(6) La classe incluse dans la combinaison sera créée et détruite au fur et à mesure de la création de la classe contenante. Les combinaisons sont réutilisées en boîte noire et peuvent être définies dynamiquement au moment de l'exécution en obtenant d'autres références d'objet ou des pointeurs du même type. L’inconvénient est qu’il y a trop d’objets dans le système.
(7) Le principe de conception OO est de combiner d’abord, puis d’hériter.

L'héritage multiple et ses problèmes d'ambiguïté

héritage multiple
(1) L'héritage multiple signifie qu'une sous-classe a plusieurs classes parents
(2)Démonstration d'héritage multiple
(3) Il n'y a pas de différence évidente entre les principes de l'héritage multiple et de l'héritage unique.
(4) L'héritage multiple peut conduire à des problèmes d'ambiguïté
L'ambiguïté de l'héritage multiple 1
(1) Scénario : C a un héritage multiple de A et B, il y aura donc une ambiguïté lors de l'appel de membres portant les mêmes noms de A et B dans C.
(2) Raison : C hérite d'un membre avec le même nom (domaine d'espace de noms différent) de A et B, donc lors d'un appel avec un objet de C, le compilateur ne peut pas déterminer lequel nous voulons appeler.
(3) Solution 1 : Pour éviter cela, laissez les noms des membres publics de A et B ne pas entrer en conflit à plusieurs reprises. Mais cela est parfois incontrôlable.
(4) Solution 2 : spécifiez clairement lequel appeler lors du codage, utilisez cA::func() pour spécifier clairement que la fonction de la classe A est appelée à la place de la fonction de la classe B.
(5) Solution 3 : redéfinissez la fonction en C, puis la fonction en C sera appelée et la fonction en A et B sera masquée.
(6) Résumé : Cela peut être résolu, mais il n’y a pas de bonne solution.

L'ambiguïté de l'héritage multiple 2
(1) Scénario : problème d’héritage des diamants.Autrement dit, A est la classe ancêtre, B1:A, B2:A, C:B1,B2. À ce stade, il y aura une ambiguïté lors de l'utilisation de l'objet de C pour appeler une méthode dans A.
(2) Analyse : c.func() est ambigu, cA::func() est également ambigu, mais c.B1::func() et c.B2::func() ne sont pas ambigus
(3) Solution : identique au problème 1, mais le problème 2 est plus subtil et plus difficile à éviter

Insérer la description de l'image ici

// 祖类
class Aa {
 public:
  void show() { std::cout << "A's method" << std::endl; }
};

// 派生类 B1 和 B2,从 A 继承
class B1 : public Aa {
 public:
  void show() { std::cout << "B1's show" << std::endl; }
  void showB1() { std::cout << "B1's method" << std::endl; }
};

class B2 : public Aa {
 public:
  void show() { std::cout << "B2's show" << std::endl; }
  void showB2() { std::cout << "B2's method" << std::endl; }
};

// 派生类 C,从 B1 和 B2 继承
class C : public B1, public B2 {
 public:
  void showC() { std::cout << "C's method" << std::endl; }
};

int test070103() {
  C c;
  // c.Aa::show();    // 调用 A 的方法 不可以
  c.Aa::B1::show();  // 调用 A 的方法 不可以
  c.B2::Aa::show();  // 调用 A 的方法 不可以
  c.B1::show();      // 调用 B1 的方法
  c.B2::show();      // 调用 B2 的方法
  c.showB1();        // 调用 B1 的方法
  c.showB2();        // 调用 B2 的方法
  c.showC();         // 调用 C 的方法
  return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

L'héritage virtuel résout le problème d'ambiguïté de l'héritage du diamant

Comment utiliser l'héritage virtuel
(1) Scénario : l'héritage Diamond entraîne des problèmes d'ambiguïté. Essentiellement, il y a deux objets A contenus dans B1 et B2 dans la classe petit-enfant C, il y a donc une ambiguïté.
(2) Solution d'héritage virtuel : laissez B1 et B2 hériter de A virtuellement, puis C peut hériter de B1 et B2 normalement.
(3) L'héritage virtuel est aussi simple qu'il est. Il est créé pour résoudre le problème d'ambiguïté de l'héritage du diamant. Il n'a aucune relation directe avec les fonctions virtuelles (pour obtenir des caractéristiques polymorphes).

Le principe de mise en œuvre de l'héritage virtuel
(1) Le principe de l'héritage virtuel est le suivant : pointeur de table de classe de base virtuelle vbptr et table virtuelle de table de classe de base virtuelle
(2)Référence :https://blog.csdn.net/xiejingfa/article/details/48028491

Insérer la description de l'image ici

Résumer

Comprenez ce qu'est une combinaison. Il existe de nombreuses variables membres d'autres types de classe dans une classe.
Comprendre la différence entre composition et héritage
Ambiguïté : si vous exécutez une fonction, ce n'est pas nécessairement celle que vous souhaitez spécifier.
Solution : utilisez cA::func() pour spécifier explicitement la classe appelée
L'héritage virtuel est un peu comme la compilation conditionnelle. Il n'est pas nécessaire de l'introduire une seule fois pour obtenir l'effet d'introduction.

Les dossiers d’études et les contacts en cas d’infraction seront supprimés.
Source : Classe Internet des objets du professeur Zhu