Eficaz C ++ cláusula 39: (a uso racional y juicioso de la herencia privada) de la herencia orientada a objetos

En primer lugar, nos dicen sobre la sintaxis de la herencia privada

  • Una clase derivada privado a heredar después de la clase base:
    • ① Todo el contenido (si, protegido, pública y privada) de la clase base en una clase derivada no es accesible
    • ② objetos de clase derivados ya no se pueden convertir en un objeto de clase de base
    • ③ todavía puede reemplazar el método miembro de la clase base / ocultar la clase base

Dos, medios de herencia privada algo?

  • medios herencia privada implementada en términos de (de acuerdo a darse cuenta de algo):
    • Supongamos que se deja que el privado heredado de la clase D a la clase B, destinados al uso de ciertas características de la clase B para lograr la clase D , hay otro significado
    • Con 34 términos pertenecen: medios herencia privada que solamente implementan parte (que ya está implementada en la función de la clase base) se hereda, la parte de interfaz (la clase base sólo se define todavía logra) debe omitirse
  • Relación con el patrón complejo de clase:
    • La clase de modo compuesto (composición) en la cláusula 38, en el que la clase de material compuesto también tiene un sentido de "es-implementado-en-términos -de" la
    • Ambos tienen el mismo significado, pero es recomendada: uso de compuestos como sea posible, si es necesario el uso de la herencia privada
    • ¿Cuándo va a ser necesario el uso privado?
      • Sobre todo cuando está protegido miembros y / o funciones virtuales que participan entraron. Cuando la clase base de la clase derivada quieren acceso protegido componente override o un grupo de uno o más clase deseada funciones virtuales
      • Otro caso es el pilar cuando el espacio lo suficientemente estacas inició la herencia privada (descrito más adelante)

En tercer lugar, el caso de demostración

  • Supongamos que tenemos una demanda de este tipo:
    • Tenemos una clase Widget, ahora quiere saber el número de función miembro que se llama el Widget
    • Ahora tenemos absolutamente modificamos clase Widget, se registra el número de veces que cada miembro de la función se llama
    • Para lograr esto, se definen los siguientes temporizador que será periódicamente los datos estadísticos (número de estadísticas de cada miembro de la función se llama)
class Timer {
public:
    explicit Timer(int tickFrequency);
    virtual void onTick()const; //定时器每滴答一次,此函数就被自动调用一次
};
  • Ahora tenemos que:
    • clase temporizador se establece de acuerdo con la frecuencia de las garrapatas hacia adelante, cada tic es llamado función virtual
    • Ahora necesitamos los hereda de la clase Widget de temporizador, y luego redefinir la función virtual, y luego utilizar esta función para Widget datos estadísticos (número de estadísticas para cada miembro de la función se llama)

① enfoque equivocado: la herencia de una manera pública

  • El camino equivocado es dejar Widget de manera pública para heredar temporizador, vuelva a grabar su función virtual
class Timer {
public:
    explicit Timer(int tickFrequency);
    virtual void onTick()const; //定时器每滴答一次,此函数就被自动调用一次
};

class Widget :public Timer {
public:
    virtual void onTick()const;
};
  • ¿Por qué error:
    • Es, una relación es similar: sabemos que no es un temporizador de widgets, que no siempre debe llamar a una función Widget onTick (), ¿verdad? Esto muestra muy extraño
    • Además, el consejo sería contrario a los términos de 18: Realizar las interfaces fáciles de usar correctamente, no puede ser fácilmente mal uso

② para heredar manera privada

  • Con el fin de completar los requisitos anteriores, podemos dejar que el widget de manera privada heredada del temporizador
  • Código es el siguiente:
class Timer {
public:
    explicit Timer(int tickFrequency);
    virtual void onTick()const; //定时器每滴答一次,此函数就被自动调用一次
};

class Widget :private Timer {
private:
    virtual void onTick()const; //查看Widget的数据..等等
};
  • Volvemos a escribir en Wiget en el onTick () función, pero lo declare como privada, no se puede declarar como interfaces públicas, porque si se declara como pública, una vez más con la herencia pública es similar a la anterior

③ implementada en la forma de un compuesto

  • En términos de 38 que introdujimos, formas complejas de clase también tiene un sentido de "está implementado-en-términos -de" , por lo que también pueden utilizar el modelo compuesto para lograr esta función
  • Código es el siguiente:
class Timer {
public:
    explicit Timer(int tickFrequency);
    virtual void onTick()const; //定时器每滴答一次,此函数就被自动调用一次
};

class Widget{
public:
private:
    class WidgetTimer :public Timer {
    public:
        virtual void onTick()const;
    };
    WidgetTimer timer;
};

  • Derivamos una clase derivada WidgetTimer un temporizador y reescribir función onTick (), y luego definir un objeto de clase WidgetTimer definido en la clase Widget en
  • El mismo problema, se recomienda el uso del modo compuesto y sin el uso de la herencia privada es recomendable por dos razones:
    • clase derivada de ① Prevent Widget para anular la función onTick ():
      • En la herencia: Si Wiget ha definido una clase derivada, no desea que las clases derivadas para anular la función onTick (), pero esto no podía parar
      • En el modo de composición: clase Widget deriva no puede tener la oportunidad de volver a escribir onTick (función), y porque la clase es WidgetTimer Widget de un miembro privado interno, la clase derivada no puede acceder a
    • ② Widget dependencia de la compilación se puede reducir al mínimo:
      • En la herencia: Si la herencia y el temporizador de widgets, las definiciones de cronómetro y cuando se compila el Widget necesitan saber (no sólo la declaración), por lo que podría contener #include "Timer.h" tal cosa en el archivo de cabecera en el Widget
      • En el modo compuesto: Supongamos que modificamos el compuesto modelo anterior, definida fuera de la Widget WidgetTimer, a continuación, un puntero a la definición en el Widget WidgetTimer, sólo que esta vez con el Widget puede WidgetTimer declarativa, tiempo, entonces no compilación cuando Widget ninguna necesidad de nada y el temporizador. Para sistemas grandes, esto es una medida muy importante

Cuatro, la herencia privada Otro escenario de uso

  • se utiliza la herencia privada: cuando la clase base sin ninguna clase de datos
  • Clase base está generalmente: no hay variables miembro no estáticos, ninguna función virutal (debido a la existencia de una función tal traerá una VPTR para cada objeto, véase el punto 7), no hay clases base virtuales (tales como clases de base se escriba resultado en un aumento del volumen, véase el punto 40)

presentación de un caso

  • Cuando una clase no tiene variables miembro, el compilador se ajusta automáticamente su tamaño (diferentes compiladores), es usualmente de 1 byte (C ++ colocación predeterminada en una clase vacía char). Por ejemplo:
class Empty {}; //空类

sizeof(Empty);  //1字节
  • Las reglas anteriores se aplican a las clases separadas, si se ha derivado de clases, y los miembros de la clase derivada, entonces esta regla desaparecerá. Por ejemplo:
class Empty {};

class HoldsAnint :private Empty {
private:
    int x;
};

sizeof(HoldsAnint); //4
  • Esta regla se llama EBO: optimización acumulada en blanco (optimización de base de vacío). Si está muy preocupado por el programa espacial, vale la pena señalar que las EBO
  • También tenga en cuenta: EBO herencia generalmente sólo individual (en lugar de la herencia múltiple) sea viable
  • Por ejemplo, hay muchas implementaciones STL utilizarán las clases vacías. Por ejemplo binary_function unary_func y similares. EBO rara vez aumentar el tamaño de la herencia de una clase derivada

V. Resumen

  • medios herencia privada "está implementado en los términos de-(de acuerdo para lograr algo)." Por lo general es más bajo que el compuesto nivel (composición) de. Pero cuando la clase derivada necesita tener acceso a miembros de la clase de base protegidas o necesidades para redefinir función virtual heredado, por lo que el diseño razonable
  • Y compuesto (composición) diferente, la herencia privada puede causar la optimización de base vacía. Este programa se ha comprometido a desarrolladores de bibliotecas "minimizar el tamaño del objeto" se refiere, puede ser importante
Liberadas 1525 artículos originales · ganado elogios 1085 · Vistas de 450.000 +

Supongo que te gusta

Origin blog.csdn.net/qq_41453285/article/details/104835285
Recomendado
Clasificación