Compartir tecnología

C: La diferencia entre composición y herencia

2024-07-12

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

Introducción a la composición y comparación con la herencia.

¿Qué es la combinación?
(1) Composición significa utilizar objetos de varias otras clases como miembros dentro de una clase.
(2) Utilice el árbol de clases para explicar casos
(3) La combinación también es un método de reutilización de código, y su esencia esEstructuraIncluir

#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

Insertar descripción de la imagen aquí

Comparación de las características de herencia y composición.
(1) La herencia es una especie de (es a) La relación es transitiva y no simétrica.
(2) La combinación es la relación de una parte de (tiene un),
(3) La herencia es la reutilización de la caja blanca. Debido a que la herencia de clases nos permite anular los detalles de implementación de la clase principal de acuerdo con nuestra propia implementación, la implementación de la clase principal es visible para la clase secundaria.
(4) La característica de reutilización de caja blanca de la herencia destruye la característica de encapsulación de la clase hasta cierto punto, porque expondrá los detalles de implementación de la clase principal a la subclase.
(5) La combinación pertenece a la reutilización de cajas negras.Los detalles internos del objeto contenido no son visibles para el mundo exterior, por lo que su encapsulación es relativamente buena y la interdependencia en la implementación es relativamente pequeña.
(6) La clase incluida en la combinación se creará y destruirá a medida que se cree la clase contenedora. Las combinaciones son reutilización de caja negra y se pueden definir dinámicamente en tiempo de ejecución obteniendo otras referencias de objetos o punteros del mismo tipo. La desventaja es que hay demasiados objetos en el sistema.
(7) El principio de diseño OO es combinar primero y luego heredar.

La herencia múltiple y sus problemas de ambigüedad

herencia múltiple
(1) Herencia múltiple significa que una subclase tiene varias clases principales
(2) Demostración de herencia múltiple
(3) No existe una diferencia obvia entre los principios de herencia múltiple y herencia única.
(4) La herencia múltiple puede provocar problemas de ambigüedad
La ambigüedad de la herencia múltiple 1
(1) Escenario: C tiene herencia múltiple de A y B, por lo que habrá ambigüedad al llamar a miembros con los mismos nombres de A y B en C.
(2) Motivo: C hereda un miembro con el mismo nombre (dominio de espacio de nombres diferente) de A y B, por lo que cuando se llama con un objeto de C, el compilador no puede determinar a cuál queremos llamar.
(3) Solución 1: Para evitar que esto ocurra, permita que el nombre de los miembros públicos de A y B no entre en conflicto repetidamente. Pero esto a veces es incontrolable.
(4) Solución 2: especifique claramente a cuál llamar al codificar, use cA::func() para especificar claramente que se llama a la función de clase A en lugar de a la función de clase B.
(5) Solución 3: Redefina la función en C, luego se llamará a la función en C y se ocultará la función en A y B.
(6) Resumen: Se puede solucionar, pero no existe una buena solución.

La ambigüedad de la herencia múltiple 2
(1) Escenario: problema de herencia de diamantes.Es decir, A es la clase ancestral, B1: A, B2: A, C: B1, B2. En este momento, habrá ambigüedad al usar el objeto de C para llamar a un método en A.
(2) Análisis: c.func() es ambiguo, cA::func() también es ambiguo, pero c.B1::func() y c.B2::func() no son ambiguos
(3) Solución: Igual que en el problema 1, pero el problema 2 es más sutil y más difícil de evitar.

Insertar descripción de la imagen aquí

// 祖类
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

La herencia virtual resuelve el problema de ambigüedad de la herencia de diamantes

Cómo utilizar la herencia virtual
(1) Escenario: la herencia de diamantes genera problemas de ambigüedad. Esencialmente, hay dos objetos A contenidos en B1 y B2 en la clase secundaria C, por lo que existe ambigüedad.
(2) Solución de herencia virtual: deje que B1 y B2 hereden A virtualmente, y luego C puede heredar B1 y B2 normalmente.
(3) La herencia virtual es así de simple. Se crea para resolver el problema de ambigüedad de la herencia de diamantes y no tiene relación directa con las funciones virtuales (para lograr características polimórficas).

El principio de implementación de la herencia virtual.
(1) El principio de la herencia virtual es: puntero de tabla de clase base virtual vbptr y tabla de clase base virtual tabla virtual
(2)Referencia:https://blog.csdn.net/xiejingfa/article/details/48028491

Insertar descripción de la imagen aquí

Resumir

Comprenda qué es una combinación. Hay muchas variables miembro de otros tipos de clase en una clase.
Comprender la diferencia entre composición y herencia.
Ambigüedad: si ejecuta una función, es posible que no sea necesariamente la que desea especificar.
Solución: use cA::func() para especificar explícitamente la clase que se llama
La herencia virtual es un poco como la compilación condicional. Solo es necesario introducirla una vez y no es necesario introducirla repetidamente para lograr el efecto de introducción.

Se eliminarán los registros del estudio y los contactos de infracción.
Fuente: Aula de Internet de las cosas del profesor Zhu