2011-10-31 8 views
7

Duplicar posible:
When should I use C++ private inheritance?¿Con qué frecuencia se usa en la práctica la herencia de C++ no pública?

quería hacer esta comunidad-wiki pero no ven el botón ... alguien puede agregarlo?

No puedo pensar en ningún caso que haya derivado de una clase de una manera no pública, y no puedo recordar el código de vista no visible que hace esto.

Me gustaría escuchar ejemplos y patrones del mundo real donde sea útil.

+0

Ya no puede hacer preguntas CW. Si lo desea, puede marcar los mods para que lo haga por usted. – sbi

+0

También en territorio similar a http://stackoverflow.com/questions/2090661/protected-inheritance. Ambas preguntas muestran que hay casos en que las personas usan herencia no pública, de manera bastante defendible (¡no es que yo diga que la estás atacando!). – AAT

Respuesta

6

Su kilometraje puede variar ...

La respuesta hard-core sería que la herencia no pública es inútil.

En lo personal, lo uso en cualquiera de los dos casos:

  • me gustaría activar la optimización Base vacía si es posible (por lo general, en el código de la plantilla con los predicados pasados ​​como parámetros)
  • me gustaría reemplazar una función virtual en la clase

en cualquiera de los casos, por lo tanto yo utilizo private herencia porque la herencia en sí es un detalle de implementación.

He visto personas usando private herencia de forma más liberal, y casi sistemática, en lugar de composición al escribir envoltorios o extender comportamientos. C++ no proporciona una sintaxis de delegado "fácil", por lo que le permite escribir using Base::method; para proporcionar inmediatamente el método en lugar de escribir una llamada de reenvío adecuada (y todas sus sobrecargas). Yo diría que es mala forma, aunque ahorra tiempo.

3

Si elige heredar para desarrollar un contenedor, la herencia privada es el camino a seguir. Ya no necesita ni desea tener acceso a los métodos y miembros de su clase base desde fuera de su clase contenedora.

class B; 
class A 
{ 
public: 
    A(); 
    void foo(B b); 
}; 

class BWrap; 
class AWrap : private A 
{ 
public: 
    AWrap(); 
    void foo(BWrap b); 
}; 

//no longer want A::foo to be accessible by mistake here, so make it private 
2

heredar A veces las clases que no están teniendo ningún virtual funciones ni un virtual destructor (por ejemplo contenedores STL), puede que tenga que ir para public herencia no. p.ej.

template<typename T> 
struct MyVector : private std::vector<T> 
{ ... }; 

Esto no permitir, mangos (puntero o de referencia) de la base (vector<>) de hacerse con derivados class (MyVector<>):

vector<int> *p = new MyVector<int>; // compiler error 
... 
delete p; // undefined behavior: ~vector() is not 'virtual'! 

Dado que, obtenemos error del compilador en la primera línea misma , nos salvaremos del comportamiento indefinido en la línea siguiente.

+0

Pero ¿por qué usaría la herencia privada en lugar de la composición aquí;)? –

+0

@MatthieuM., Aunque es una cuestión de gusto, pero la composición no permitirá las operaciones como 'is_base_of <>'. :) – iammilind

+0

Sé que se han producido algunos cambios en las reglas de acceso en contextos SFINAE en C++ 11 ... No creo que 'is_base_of' permita el acceso' público' al conocimiento de que se usa la clase base, y ' Los clientes privados siempre pueden consultar al miembro en sí ... así que ¿de qué sirve? –

2

Si proviene de una clase sin un destructor virtual, entonces la herencia pública da lugar a una posibilidad que los usuarios de la clase pueden llamar eliminar en un puntero a base, lo que conduce a un comportamiento indefinido.
En tal escenario, tiene sentido usar Herencia privada.

El ejemplo más común de esto es derivar en privado de contenedores STL que no tienen destructores virtuales.


C++FAQ tiene un excelente ejemplo de la herencia privada que se extiende a muchos escenarios de la vida real.

A, uso legítimo a largo plazo para la herencia privada es cuando se quiere construir una clase Fred que utiliza código en una clase de Wilma, y ​​el código de la clase Wilma necesita invocar funciones miembro de su nueva clase, Fred . En este caso, Fred llama a los no virtuales en Wilma, y ​​Wilma llama (generalmente virtuales puros) en sí mismo, que son reemplazados por Fred. Esto sería mucho más difícil de hacer con la composición.

Ejemplo de código:

class Wilma { 
protected: 
    void fredCallsWilma() 
    { 
     std::cout << "Wilma::fredCallsWilma()\n"; 
     wilmaCallsFred(); 
    } 
    virtual void wilmaCallsFred() = 0; // A pure virtual function 
}; 

class Fred : private Wilma { 
public: 
    void barney() 
    { 
     std::cout << "Fred::barney()\n"; 
     Wilma::fredCallsWilma(); 
    } 
protected: 
    virtual void wilmaCallsFred() 
    { 
     std::cout << "Fred::wilmaCallsFred()\n"; 
    } 
}; 
2

Desde private herencia tiene como su uso sólo se conoce aplicación herencia, y ya que este siempre se podría hacer uso de la contención lugar (que es menos fácil de usar, pero mejor resume la relación), yo diría que es utilizado también a menudo.

(Dado que nadie me dijo lo que significa protected herencia, vamos a suponer que nadie sabe lo que es y pretender que no existe.)

+0

+1 para el fragmento de la herencia 'protected'.A veces me pregunto si no se introdujo simplemente por consistencia (es decir, dado que 'protected' también es un especificador de acceso). –

+0

El ítem 24 en "Exceptional C++" de Herb Sutter proporciona el único ejemplo que he visto de herencia protegida. – Gorpik

+0

@ Matthieu: Creo que la herencia 'protegida' no se introdujo realmente en el lenguaje. En lugar de eso, nadie se molestó en retirarlo. ':)' – sbi

0

herencia no pública (casi siempre privadas) se utiliza al heredar (solo) comportamiento, y no interfaz. Lo he usado principalmente, pero no exclusivamente, en mixins.

Para una buena discusión sobre el tema, es posible que desee leer Barton y Nackman (la Ciencia y la Ingeniería C++:. Una introducción con Advanced Técnicas y ejemplos, ISBN 0-201-53393-6 A pesar de la   nombre, grandes partes del libro son aplicables a todas las aplicaciones de C++, no solo científicas y de ingeniería . Y a pesar de su fecha, todavía vale la pena leerlo)

Cuestiones relacionadas