Primero, "STL" no es un término oficial, es el nombre de la biblioteca propuesta para incluir en la Biblioteca Estándar de C ++ cuando no había contenedores. Proporciona esencialmente plantillas de contenedor y algoritmos.
Ahora, estas plantillas de contenedor y algoritmos son ... plantillas, por lo que producen tipos según sea necesario. No se basan en la herencia desde el punto de vista del usuario.
Sin embargo, la biblioteca estándar especifica esencialmente la interfaz de la biblioteca, no la implementación. Muchas implementaciones de STL utilizarán un poco de orientación a objetos en su implementación, pero como usuario no lo verá si no se sumerge en el código fuente de sus implementaciones (que deben exponerse ya que es esencialmente un código de plantilla).
Aprendí que la función de miembro virtual que justifica el OO está en contradicción con la plantilla, ¿es esto correcto?
No, son conceptos ortogonales que proporcionan conjuntos muy diferentes de ventajas y desventajas. De hecho, en C ++, una de las principales ventajas de usar dicho lenguaje es que tiene ambos disponibles y el uso de uno no cancela el uso del otro. Incluso es una gran ventaja. Por ejemplo, uno de los modismos más interesantes en C ++ es CRTP que usa tanto plantillas como herencia. La idea es que la parte de herencia le permite extender varios tipos con un comportamiento y datos comunes, como una clase base; mientras que la parte de la plantilla se asegura de generar clases base específicas para cada niño, haciendo imposible tener un puntero a todas las clases usando la clase CRTP como base. Esto es extremadamente útil y no permite jugar con la herencia donde no debería haberla.
También he implementado sistemas de distribución de eventos muy genéricos que no conocían los tipos de eventos ni los tipos de escucha, pero combinaron código interno dinámico y estático que juntos permitieron generar los tipos internos correctos correspondientes a los tipos de tiempo de ejecución correctos.
Y ese es el punto: no siempre se necesita "orientación a objetos". De hecho, la mayoría de las veces no lo necesita en absoluto, necesita definir algunos tipos y usarlos directamente como parte diferente de algún tipo de motor abstracto (composición). No siempre necesita un código genérico, también conocido como plantillas. A veces lo necesita para generalizar una función que se aplica a varios tipos no relacionados. Cuando están relacionados, puede usar su clase base y no necesitar plantillas.
Tienen diferentes ventajas y costos completamente diferentes, por lo que son buenos para combinar para resolver problemas complejos.
STL es un buen ejemplo de un problema en el que la mayor parte se trata de proporcionar tipos (contenedores) y funciones (algoritmos) que están relacionados con un tipo determinado en lugar de una jerarquía de objetos de tiempo de ejecución. En la biblioteca estándar, los flujos se hacen de una manera típica de la orientación a objetos: es una jerarquía de clases de flujo que hace cosas diferentes de una manera que permite definir una clase de flujo secundario que combina diferentes comportamientos / capacidades. Allí, la orientación a objetos es útil, incluso si algunas personas prefieren que se parezca más al STL (no soy un especialista en el tema).
Entonces, piense en ellas como herramientas muy diferentes, como un destornillador y un martillo. C ++ no te deja pensar con solo una herramienta en mente.