versiones tipos sirve que para fuente dev definicion datos colas codigo caracteristicas c++ oop templates stl

tipos - ¿Por qué el C++ STL está tan basado en plantillas?(y no en*interfaces*)



tipos de datos en c++ (13)

se supone que los tipos de plantilla deben seguir un "concepto" (Iterador de entrada, Iterador hacia adelante, etc.) donde los detalles reales del concepto se definen completamente por la implementación de la función / clase de la plantilla, y no por la clase del tipo Se utiliza con la plantilla, que es un tanto anti-uso de OOP.

Creo que malinterpretas el uso pretendido de los conceptos por plantillas. Forward Iterator, por ejemplo, es un concepto muy bien definido. Para encontrar las expresiones que deben ser válidas para que una clase sea un iterador directo y su semántica, incluida la complejidad computacional, consulte el estándar o en http://www.sgi.com/tech/stl/ForwardIterator.html (tienes que seguir los enlaces a Entrada, Salida e Iterador Trivial para verlo todo).

Ese documento es una interfaz perfectamente buena y "los detalles reales del concepto" se definen allí mismo. No están definidos por las implementaciones de los iteradores hacia adelante, y tampoco están definidos por los algoritmos que usan los iteradores hacia adelante.

Las diferencias en cómo se manejan las interfaces entre STL y Java son triples:

1) STL define expresiones válidas usando el objeto, mientras que Java define métodos que deben ser invocables en el objeto. Por supuesto, una expresión válida puede ser una llamada al método (función miembro), pero no tiene que serlo.

2) Las interfaces Java son objetos de tiempo de ejecución, mientras que los conceptos de STL no son visibles en tiempo de ejecución incluso con RTTI.

3) Si no hace válidas las expresiones válidas necesarias para un concepto de STL, obtendrá un error de compilación no especificado al crear una instancia de una plantilla con el tipo. Si no implementas un método requerido de una interfaz Java, obtienes un error de compilación específico que lo dice.

Esta tercera parte es si te gusta una especie de "escritura de pato" (en tiempo de compilación): las interfaces pueden ser implícitas. En Java, las interfaces son algo explícitas: una clase "es" Iterable si y solo si dice que implementa Iterable. El compilador puede verificar que todas las firmas de sus métodos estén presentes y sean correctas, pero la semántica aún está implícita (es decir, está documentada o no, pero solo más código (pruebas unitarias) puede decirle si la implementación es correcta).

En C ++, al igual que en Python, tanto la semántica como la sintaxis están implícitas, aunque en C ++ (y en Python si obtienes el preprocesador de escritura fuerte) obtienes ayuda del compilador. Si un programador requiere una declaración explícita de interfaces al estilo de Java por parte de la clase implementadora, entonces el enfoque estándar es usar rasgos de tipo (y la herencia múltiple puede evitar que sea demasiado detallado). Lo que falta, comparado con Java, es una plantilla única que puedo instanciar con mi tipo, y que se compilará si y solo si todas las expresiones requeridas son válidas para mi tipo. Esto me diría si he implementado todos los bits requeridos, "antes de usarlo". Eso es una conveniencia, pero no es el núcleo de la POO (y todavía no prueba la semántica, y el código para probar la semántica naturalmente también probará la validez de las expresiones en cuestión).

STL puede o no ser lo suficientemente OO para su gusto, pero ciertamente separa la interfaz limpiamente de la implementación. Carece de la capacidad de Java para reflexionar sobre las interfaces, e informa de las violaciones de los requisitos de la interfaz de manera diferente.

puede indicar la función ... espera un iterador hacia adelante solo al ver su definición, en la que debería ver la implementación o la documentación para ...

Personalmente creo que los tipos implícitos son una fortaleza, cuando se usan apropiadamente. El algoritmo dice lo que hace con sus parámetros de plantilla, y el implementador se asegura de que esas cosas funcionen: es exactamente el denominador común de lo que deberían hacer las "interfaces". Además, con STL, es poco probable que esté utilizando, digamos, std::copy función de encontrar su declaración directa en un archivo de encabezado. Los programadores deben estar trabajando en lo que una función toma en función de su documentación, no solo en la firma de la función. Esto es cierto en C ++, Python o Java. Hay limitaciones sobre lo que se puede lograr con la escritura en cualquier idioma, y ​​tratar de usar la escritura para hacer algo que no hace (ver semántica) sería un error.

Dicho esto, los algoritmos STL usualmente nombran los parámetros de su plantilla de manera que quede claro qué concepto se requiere. Sin embargo, esto es para proporcionar información adicional útil en la primera línea de la documentación, no para hacer declaraciones más informativas. Hay más cosas que necesita saber que se pueden encapsular en los tipos de parámetros, por lo que debe leer los documentos. (Por ejemplo, en los algoritmos que toman un rango de entrada y un iterador de salida, es probable que el iterador de salida necesite suficiente "espacio" para un cierto número de salidas en función del tamaño del rango de entrada y tal vez los valores en él. Intente escribirlo con fuerza. )

Aquí está Bjarne sobre interfaces declaradas explícitamente: http://www.artima.com/cppsource/cpp0xP.html

En genéricos, un argumento debe ser de una clase derivada de una interfaz (el equivalente de C ++ a interfaz es una clase abstracta) especificada en la definición del genérico. Eso significa que todos los tipos de argumentos genéricos deben encajar en una jerarquía. Eso impone restricciones innecesarias en los diseños requiere una previsión irrazonable por parte de los desarrolladores. Por ejemplo, si escribes un genérico y yo defino una clase, las personas no pueden usar mi clase como un argumento para tu genérico a menos que yo supiera sobre la interfaz que especificaste y de la que derivé mi clase. Eso es rígido.

Mirándolo de otra manera, con la escritura de pato puede implementar una interfaz sin saber que la interfaz existe. O alguien puede escribir una interfaz deliberadamente de manera tal que su clase la implemente, habiendo consultado sus documentos para ver que no le piden nada que ya no haga. Eso es flexible.

Quiero decir, aparte de su nombre obligatorio (la biblioteca de plantillas estándar) ...

C ++ inicialmente tenía la intención de presentar los conceptos OOP en C. Es decir: podría decir qué podría y qué no podría hacer una entidad específica (independientemente de cómo lo haga) en función de su clase y jerarquía de clases. Algunas composiciones de habilidades son más difíciles de describir de esta manera debido a la problemática de la herencia múltiple, y el hecho de que C ++ apoya el concepto de interfaces de una manera un tanto torpe (en comparación con Java, etc.), pero está ahí (y podría estarlo) mejorado).

Y luego las plantillas entraron en juego, junto con el STL. El STL parecía tomar los conceptos OOP clásicos y desecharlos, usando plantillas en su lugar.

Debe haber una distinción entre los casos en que las plantillas se utilizan para generalizar tipos donde los tipos temaselves son irrelevantes para el funcionamiento de la plantilla (contenedores, por ejemplo). Tener un vector<int> tiene perfecto sentido.

Sin embargo, en muchos otros casos (iteradores y algoritmos), se supone que los tipos de plantilla deben seguir un "concepto" (Iterador de entrada, Iterador hacia adelante, etc.) donde los detalles reales del concepto se definen completamente por la implementación de la plantilla. función / clase, y no por la clase del tipo utilizado con la plantilla, que es un tanto anti-uso de OOP.

Por ejemplo, puedes decir la función:

void MyFunc(ForwardIterator<...> *I);

Actualización: Como no estaba claro en la pregunta original, ForwardIterator está bien para tener la plantilla para permitir cualquier tipo de ForwardIterator. Lo contrario es tener ForwardIterator como un concepto.

espera un iterador hacia adelante solo al ver su definición, donde necesitaría ver la implementación o la documentación para:

template <typename Type> void MyFunc(Type *I);

Puedo hacer dos afirmaciones a favor del uso de plantillas: el código compilado se puede hacer más eficiente, compilando a medida la plantilla para cada tipo utilizado, en lugar de usar vtables. Y el hecho de que las plantillas se pueden utilizar con tipos nativos.

Sin embargo, estoy buscando una razón más profunda por la cual abandonar la OOP clásica en favor de las plantillas para el STL? (Suponiendo que lea tan lejos: P)


"OOP para mí significa solo mensajes, retención local y protección y ocultamiento del proceso de estado, y una vinculación final extrema de todas las cosas. Se puede hacer en Smalltalk y en LISP. Hay posiblemente otros sistemas en los que esto es posible, pero No estoy al tanto de ellos ". - Alan Kay, creador de Smalltalk.

C ++, Java y la mayoría de los otros lenguajes están bastante lejos del OOP clásico. Dicho esto, defender las ideologías no es terriblemente productivo. C ++ no es puro en ningún sentido, por lo que implementa una funcionalidad que parece tener sentido pragmático en ese momento.


¿Cómo haces comparaciones con ForwardIterator *? Es decir, ¿cómo verifica si el artículo que tiene es lo que está buscando o si lo ha pasado?

La mayoría de las veces, usaría algo como esto:

void MyFunc(ForwardIterator<MyType>& i)

lo que significa que sé que estoy apuntando a MyType''s, y sé cómo compararlos. Aunque parece una plantilla, en realidad no es (no hay palabra clave "plantilla").


¿Por qué un diseño OOP puro para una estructura de datos y una biblioteca de algoritmos sería mejor? OOP no es la solución para todo.

En mi humilde opinión, STL es la biblioteca más elegante que he visto en mi vida :)

por tu pregunta,

no necesita polimorfismo en tiempo de ejecución, es una ventaja para STL implementar la biblioteca utilizando polimorfismo estático, eso significa eficiencia. ¡Trate de escribir una clasificación genérica o una distancia o cualquier otro algoritmo que se aplique a TODOS los contenedores! ¡Su clasificación en Java llamaría funciones que son dinámicas a través de n niveles para ser ejecutadas!

Necesitas cosas estúpidas como el boxeo y el desempaquetado para ocultar suposiciones desagradables de los llamados lenguajes OOP puros.

El único problema que veo con STL y las plantillas en general son los terribles mensajes de error. Lo cual se resolverá utilizando Conceptos en C ++ 0X.

Comparando STL con colecciones en Java es como comparar Taj Mahal con mi casa :)


El problema básico con

void MyFunc(ForwardIterator *I);

¿Cómo puede obtener de forma segura el tipo de cosa que devuelve el iterador? Con las plantillas, esto se hace por ti en tiempo de compilación.


Esta pregunta tiene muchas grandes respuestas. También hay que mencionar que las plantillas soportan un diseño abierto. Con el estado actual de los lenguajes de programación orientados a objetos, uno tiene que usar el patrón de visitante cuando se trata de tales problemas, y el OOP verdadero debe admitir el enlace dinámico múltiple. Ver métodos abiertos múltiples para C ++, P. Pirkelbauer, et.al. Para una lectura muy interesante.

Otro punto interesante de las plantillas es que también se pueden usar para el polimorfismo en tiempo de ejecución. Por ejemplo

template<class Value,class T> Value euler_fwd(size_t N,double t_0,double t_end,Value y_0,const T& func) { auto dt=(t_end-t_0)/N; for(size_t k=0;k<N;++k) {y_0+=func(t_0 + k*dt,y_0)*dt;} return y_0; }

Tenga en cuenta que esta función también funcionará si Valuees un vector de algún tipo ( no std :: vector, que debe llamarse std::dynamic_arraypara evitar confusiones)

Si funces pequeño, esta función ganará mucho con el alineamiento. Ejemplo de uso

auto result=euler_fwd(10000,0.0,1.0,1.0,[](double x,double y) {return y;});

En este caso, debe saber la respuesta exacta (2.718 ...), pero es fácil construir una EDO simple sin solución elemental (Sugerencia: use un polinomio en y).

Ahora, tiene una gran expresión funcy usa el solucionador ODE en muchos lugares, por lo que su ejecutable se contamina con ejemplificaciones de plantillas en todas partes. ¿Qué hacer?Lo primero que hay que notar es que un puntero de función normal funciona. Luego desea agregar curry para escribir una interfaz y una instanciación explícita

class OdeFunction { public: virtual double operator()(double t,double y) const=0; }; template double euler_fwd(size_t N,double t_0,double t_end,double y_0,const OdeFunction& func);

Pero la creación de instancias anterior solo funciona para double, por qué no escribir la interfaz como plantilla:

template<class Value=double> class OdeFunction { public: virtual Value operator()(double t,const Value& y) const=0; };

y especializarse en algunos tipos de valores comunes:

template double euler_fwd(size_t N,double t_0,double t_end,double y_0,const OdeFunction<double>& func); template vec4_t<double> euler_fwd(size_t N,double t_0,double t_end,vec4_t<double> y_0,const OdeFunction< vec4_t<double> >& func); // (Native AVX vector with four components) template vec8_t<float> euler_fwd(size_t N,double t_0,double t_end,vec8_t<float> y_0,const OdeFunction< vec8_t<float> >& func); // (Native AVX vector with 8 components) template Vector<double> euler_fwd(size_t N,double t_0,double t_end,Vector<double> y_0,const OdeFunction< Vector<double> >& func); // (A N-dimensional real vector, *not* `std::vector`, see above)

Si la función hubiera sido diseñada alrededor de una interfaz primero, entonces se habría visto obligado a heredar de ese ABC. Ahora tiene esta opción, así como el puntero de función, lambda o cualquier otro objeto de función. La clave aquí es que debemos tener operator()(), y debemos poder usar algunos operadores aritméticos en su tipo de retorno. Por lo tanto, la maquinaria de la plantilla se rompería en este caso si C ++ no tuviera una sobrecarga del operador.


La respuesta corta es "porque C ++ se ha movido". Sí, a finales de los 70, Stroustrup tenía la intención de crear una C mejorada con capacidades OOP, pero eso fue hace mucho tiempo. Cuando el idioma se estandarizó en 1998, ya no era un lenguaje OOP. Era un lenguaje multi-paradigma. Ciertamente tenía algo de soporte para el código OOP, pero también tenía una plantilla de lenguaje completa superpuesta, permitía la metaprogramación en tiempo de compilación y la gente había descubierto la programación genérica. De repente, OOP simplemente no parecía tan importante. No cuando podemos escribir código más simple, más conciso y más eficiente mediante el uso de técnicas disponibles a través de plantillas y programación genérica.

OOP no es el santo grial. Es una linda idea, y fue una gran mejora con respecto a los lenguajes de procedimiento en los años 70 cuando se inventó. Pero honestamente no es todo lo que parece. En muchos casos, es torpe y detallado y realmente no promueve código o modularidad reutilizables.

Es por eso que la comunidad de C ++ está hoy mucho más interesada en la programación genérica, y por qué todos finalmente están comenzando a darse cuenta de que la programación funcional también es bastante inteligente. OOP por sí solo no es una vista bonita.

Intente dibujar un gráfico de dependencia de un hipotético STL "OOP-ified". ¿Cuántas clases tendrían que saber unos de otros? Habría muchas dependencias. ¿Sería capaz de incluir solo el encabezado vector , sin que también se obtenga iterator o incluso iostream ? El STL hace esto fácil. Un vector conoce el tipo de iterador que define, y eso es todo. Los algoritmos STL no saben nada . Ni siquiera necesitan incluir un encabezado de iterador, aunque todos aceptan los iteradores como parámetros. ¿Cuál es más modular entonces?

Es posible que el STL no siga las reglas de OOP como lo define Java, pero ¿no logra los objetivos de OOP? ¿No consigue reutilización, acoplamiento bajo, modularidad y encapsulación?

¿Y no logra estos objetivos mejor que una versión de OOP?

En cuanto a por qué se adoptó el STL en el lenguaje, sucedieron varias cosas que llevaron al STL.

Primero, se agregaron plantillas a C ++. Fueron agregados por la misma razón que los genéricos se agregaron a .NET. Parecía una buena idea poder escribir cosas como "contenedores de un tipo T" sin desechar el tipo de seguridad. Por supuesto, la implementación en la que se establecieron fue bastante más compleja y poderosa.

Entonces la gente descubrió que el mecanismo de plantilla que habían agregado era incluso más poderoso de lo esperado. Y alguien comenzó a experimentar con el uso de plantillas para escribir una biblioteca más genérica. Una inspirada en la programación funcional, y otra que utilizó todas las nuevas capacidades de C ++.

Lo presentó al comité de lenguaje C ++, que tardó bastante tiempo en acostumbrarse porque parecía muy extraño y diferente, pero al final se dio cuenta de que funcionaba mejor que los equivalentes tradicionales de POO que tendrían que incluir de otra manera . Así que hicieron algunos ajustes y lo adoptaron en la biblioteca estándar.

No fue una elección ideológica, no fue una elección política de "queremos ser OOP o no", sino una decisión muy pragmática. Ellos evaluaron la biblioteca y vieron que funcionaba muy bien.

En cualquier caso, las dos razones que mencionas para favorecer a la STL son absolutamente esenciales.

La biblioteca estándar de C ++ tiene que ser eficiente. Si es menos eficiente que, digamos, el código C enrollado a mano equivalente, entonces la gente no lo usaría. Eso reduciría la productividad, aumentaría la probabilidad de errores y, en general, sería una mala idea.

Y la STL tiene que trabajar con tipos primitivos, porque los tipos primitivos son todo lo que tienes en C, y son una parte importante de ambos idiomas. Si el STL no funcionara con matrices nativas, sería inútil .

Su pregunta tiene una fuerte suposición de que la POO es "mejor". Tengo curiosidad por saber por qué. Preguntas por qué "abandonaron la OOP clásica". Me pregunto por qué deberían haberse quedado con eso. ¿Qué ventajas habría tenido?


La respuesta más directa a lo que creo que está preguntando / quejándose es la siguiente: la suposición de que C ++ es un lenguaje OOP es una suposición falsa.

C ++ es un lenguaje multi-paradigma. Puede programarse según los principios de la programación orientada a objetos (OOP), se puede programar de manera procesal, se puede programar de forma genérica (plantillas) y, con C ++ 11 (anteriormente conocido como C ++ 0x), algunas cosas pueden programarse de manera funcional.

Los diseñadores de C ++ ven esto como una ventaja, por lo que argumentarían que obligar a C ++ a actuar como un lenguaje puramente OOP cuando la programación genérica resuelve mejor el problema y, bueno, más genéricamente , sería un paso atrás.


La respuesta se encuentra en esta entrevista con Stepanov, el autor de la STL:

Sí. STL no está orientado a objetos. Creo que la orientación a objetos es casi tan engañosa como la Inteligencia Artificial. Todavía tengo que ver un interesante fragmento de código que proviene de estas personas OO.


Por un momento, pensemos en la biblioteca estándar como básicamente una base de datos de colecciones y algoritmos.

Si ha estudiado la historia de las bases de datos, sin duda sabe que desde el principio, las bases de datos eran en su mayoría "jerárquicas". Las bases de datos jerárquicas se correspondían muy estrechamente con la POO clásica, específicamente, la variedad de herencia única, como la utilizada por Smalltalk.

Con el tiempo, se hizo evidente que las bases de datos jerárquicas podían usarse para modelar casi cualquier cosa, pero en algunos casos el modelo de herencia única era bastante limitante. Si tenías una puerta de madera, era útil poder mirarla como una puerta o como una pieza de alguna materia prima (acero, madera, etc.)

Así, inventaron las bases de datos de modelos de red. Las bases de datos del modelo de red se corresponden muy estrechamente con la herencia múltiple. C ++ admite completamente la herencia múltiple, mientras que Java admite una forma limitada (puede heredar de una sola clase, pero también puede implementar tantas interfaces como desee).

Tanto las bases de datos del modelo jerárquico como las del modelo de red se han desvanecido principalmente del uso de propósito general (aunque algunas permanecen en nichos bastante específicos). Para la mayoría de los propósitos, han sido reemplazados por bases de datos relacionales.

Gran parte de la razón por la que las bases de datos relacionales se hicieron cargo fue la versatilidad. El modelo relacional es funcionalmente un superconjunto del modelo de red (que a su vez es un superconjunto del modelo jerárquico).

C ++ ha seguido en gran medida el mismo camino. La correspondencia entre la herencia única y el modelo jerárquico y entre la herencia múltiple y el modelo de red son bastante obvias. La correspondencia entre las plantillas de C ++ y el modelo jerárquico puede ser menos obvia, pero de todos modos es un ajuste bastante ajustado.

No he visto una prueba formal de ello, pero creo que las capacidades de las plantillas son un superconjunto de las proporcionadas por la herencia múltiple (que es claramente un superconjunto de la inercia única). La única parte difícil es que las plantillas están mayormente vinculadas estáticamente, es decir, todo el enlace ocurre en tiempo de compilación, no en tiempo de ejecución. Como tal, una prueba formal de que la herencia proporciona un superconjunto de las capacidades de la herencia bien puede ser algo difícil y complejo (o incluso puede ser imposible).

En cualquier caso, creo que es la mayor parte de la razón real por la que C ++ no utiliza la herencia para sus contenedores; no hay ninguna razón real para hacerlo, porque la herencia solo proporciona un subconjunto de las capacidades proporcionadas por las plantillas. Dado que las plantillas son básicamente una necesidad en algunos casos, también pueden usarse en casi todas partes.


STL comenzó con la intención de proporcionar una gran biblioteca que cubra el algoritmo más comúnmente utilizado, con el objetivo de un comportamiento y rendimiento coherentes. La plantilla llegó como un factor clave para hacer que esa implementación y objetivo sea factible.

Solo para proporcionar otra referencia:

Entrevistas a Al Stevens Alex Stepanov, en marzo de 1995 de DDJ:

Stepanov explicó su experiencia laboral y la elección realizada hacia una gran biblioteca de algoritmos, que eventualmente evolucionó a STL.

Cuéntanos algo sobre tu interés a largo plazo en la programación genérica.

..... Luego me ofrecieron un trabajo en los Laboratorios Bell que trabajan en el grupo de C ++ en las bibliotecas de C ++. Me preguntaron si podía hacerlo en C ++. Por supuesto, no sabía C ++ y, por supuesto, dije que podía. Pero no pude hacerlo en C ++, porque en 1987 C ++ no tenía plantillas, que son esenciales para habilitar este estilo de programación. La herencia fue el único mecanismo para obtener la generosidad y no fue suficiente.

Incluso ahora, la herencia de C ++ no es de mucha utilidad para la programación genérica. Vamos a discutir por qué. Muchas personas han intentado usar la herencia para implementar estructuras de datos y clases de contenedor. Como sabemos ahora, hubo pocos intentos de éxito, si es que hubo alguno. La herencia de C ++ y el estilo de programación asociado con ella están dramáticamente limitados. Es imposible implementar un diseño que incluya algo tan trivial como la igualdad al usarlo. Si comienza con una clase base X en la raíz de su jerarquía y define un operador de igualdad virtual en esta clase que toma un argumento del tipo X, entonces derive la clase Y de la clase X. ¿Cuál es la interfaz de la igualdad? Tiene igualdad que compara Y con X. Usando animales como ejemplo (las personas OO aman a los animales), definen a los mamíferos y derivan jirafas de los mamíferos. Luego define un compañero de función miembro, donde el animal se aparea con el animal y devuelve un animal. Luego derivas una jirafa de un animal y, por supuesto, tiene una función en la que la jirafa se aparea con un animal y devuelve un animal. Definitivamente no es lo que quieres. Mientras que el apareamiento puede no ser muy importante para los programadores de C ++, la igualdad es. No conozco un solo algoritmo donde no se use la igualdad de algún tipo.


Según tengo entendido, Stroustrup originalmente prefería un diseño de contenedor "estilo OOP" y, de hecho, no veía ninguna otra forma de hacerlo. Alexander Stepanov es el responsable del STL, y sus objetivos no incluían "hacerlo orientado a objetos" :

Ese es el punto fundamental: los algoritmos se definen en estructuras algebraicas. Me tomó un par de años más darme cuenta de que tiene que extender la noción de estructura agregando requisitos de complejidad a los axiomas regulares. ... Creo que las teorías de iteradores son tan fundamentales para la informática como las teorías de los anillos o los espacios de Banach son fundamentales para las matemáticas. Cada vez que miraba un algoritmo, intentaba encontrar una estructura en la que está definido. Entonces, lo que quería hacer era describir algoritmos genéricamente. Eso es lo que me gusta hacer. Puedo pasar un mes trabajando en un algoritmo conocido tratando de encontrar su representación genérica. ...

STL, al menos para mí, representa la única forma en que la programación es posible. De hecho, es bastante diferente de la programación en C ++, ya que se presentó y aún se presenta en la mayoría de los libros de texto. Pero, verás, no estaba tratando de programar en C ++, estaba tratando de encontrar la manera correcta de lidiar con el software. ...

Tuve muchos comienzos falsos. Por ejemplo, pasé años tratando de encontrar algún uso para la herencia y los virtuales, antes de entender por qué ese mecanismo era fundamentalmente defectuoso y no debía usarse. Estoy muy feliz de que nadie haya podido ver todos los pasos intermedios, la mayoría de ellos eran muy tontos.

(Él explica por qué la herencia y los elementos virtuales, también conocido como diseño orientado a objetos "tenían defectos fundamentales y no deberían utilizarse" en el resto de la entrevista).

Una vez que Stepanov presentó su biblioteca a Stroustrup, Stroustrup y otros hicieron un gran esfuerzo para ingresar la norma ISO C ++ (la misma entrevista):

El apoyo de Bjarne Stroustrup fue crucial. Bjarne realmente quería STL en el estándar y si Bjarne quiere algo, lo consigue. ... Incluso me obligó a hacer cambios en STL que nunca haría por nadie más ... es la persona más inteligente que conozco. Él hace las cosas. Le tomó un tiempo entender de qué se trataba STL, pero cuando lo hizo, estaba preparado para superarlo. También contribuyó a STL defendiendo la opinión de que más de una forma de programación era válida, en contra de las críticas y el entusiasmo durante más de una década, y persiguiendo una combinación de flexibilidad, eficiencia, sobrecarga y seguridad de tipos en Plantillas que hicieron posible STL. Me gustaría decir claramente que Bjarne es el diseñador de lenguaje preeminente de mi generación.


El concepto de separar interfaz de interfaz y poder intercambiar las implementaciones no es intrínseco a la programación orientada a objetos. Creo que es una idea que surgió en el desarrollo basado en componentes como Microsoft COM. (Vea mi respuesta en ¿Qué es el desarrollo impulsado por componentes?) Al crecer y aprender C ++, las personas fueron exageradas a causa de la herencia y el polimorfismo. No fue hasta que la gente de los 90 comenzó a decir "Programar a una ''interfaz'', no a una ''implementación'' ''y'' Favorecer ''a la composición de objetos'' sobre ''herencia de clase''". (ambos de los cuales tomadas de GoF por cierto).

Luego, Java vino junto con el recolector de basura incorporado y la interfacepalabra clave, y de repente se hizo práctico separar la interfaz y la implementación. Antes de que te des cuenta, la idea se convirtió en parte de la OO. C ++, templates y STL son anteriores a todo esto.