Primeiro, "STL" não é um termo oficial, é o nome da biblioteca proposta para inclusão na Biblioteca Padrão C ++ quando não havia contêineres. Ele fornece essencialmente modelos de contêiner e algoritmos.
Agora, esses modelos de contêiner e algoritmos são ... modelos para que eles produzam tipos conforme necessário. Eles não confiam na herança do ponto de vista do usuário.
No entanto, a biblioteca padrão especifica essencialmente a interface da biblioteca, não a implementação. Muitas implementações de STL usarão um pouco de orientação a objetos em sua implementação, mas como usuário você não a verá se não mergulhar no código-fonte das implementações (que precisa ser exposto, pois é essencialmente o código do modelo).
Aprendi que a função de membro virtual que justifica o OO está em contradição com o modelo, isso está correto?
Não, são conceitos ortogonais que fornecem conjuntos muito diferentes de vantagens e contras. De fato, em C ++, uma das principais vantagens de usar essa linguagem é que você tem disponível e o uso de um não cancela o uso do outro. É até uma vantagem muito grande. Por exemplo, um dos idiomas mais interessantes em C ++ é o CRTP, que usa modelos e herança. A ideia é que a parte de herança permita estender vários tipos com um comportamento e dados comuns, como uma classe base; enquanto a parte do modelo garante a geração de classes base específicas para cada filho, impossibilitando um ponteiro para todas as classes usando a classe CRTP como base. Isso é extremamente útil e não permite mexer com a herança onde não deveria haver.
Também implementei sistemas muito genéricos de despacho de eventos que não conheciam tipos de eventos ou tipos de ouvintes, mas combinamos código dinâmico e estático internamente que juntos permitiam gerar os tipos internos corretos correspondentes aos tipos corretos de tempo de execução.
E esse é o ponto: você nem sempre precisa de "orientação a objetos". De fato, na maioria das vezes você não precisa disso, precisa definir alguns tipos e usá-los diretamente como parte diferente de algum tipo de mecanismo abstrato (composição). Você nem sempre precisa de código genérico, também conhecido como modelos. Às vezes, é necessário generalizar uma função para aplicar a vários tipos não relacionados. Quando eles estão relacionados, você pode usar a classe base e não precisa de modelos.
Eles têm vantagens diferentes e custos completamente diferentes, portanto, são bons para combinar para resolver problemas complexos.
STL é um bom exemplo de um problema em que a maioria se refere ao fornecimento de tipos (contêineres) e funções (algoritmos) relacionados a um determinado tipo, em vez de uma hierarquia de objetos de tempo de execução. Na biblioteca padrão, os fluxos são feitos de uma maneira típica da orientação a objetos: é uma hierarquia de classes de fluxo que faz coisas diferentes de uma maneira que permite definir uma classe de sub-fluxo que combina comportamentos / capacidades diferentes. Lá, a orientação a objetos é útil, mesmo que algumas pessoas prefiram que seja mais parecida com a STL (não sou especialista no assunto).
Então, pense nelas como ferramentas muito diferentes, como uma chave de fenda e um martelo. O C ++ não permite que você pense com apenas uma ferramenta em mente.