Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


Introducción al C++

... appalled at the monstrous messes that computer scientists can produce under the name of ‘improvements’.  It is to efforts such as C++ that I here refer. These artefacts are filled with frills and features but lack coherence, simplicity, understandability and implementability. If computer scientists could see that art is at the root of the best science, such ugly creatures could never take birth.”   R.P.Mody "C in Education and Software Engineering", ACM SIGCSE Bulletin Vol.23 No. 3 September 1991.

§1  Presentación del lenguaje C++

Con independencia de las explicaciones más técnicas que se incluyen en el capítulo 1, digamos aquí que el lenguaje C++ es el resultado de una "larga" evolución (informáticamente hablando). Las cosas no nacieron de improviso como son ahora; se ha ido puliendo y completando a lo largo del tiempo. Además de importar conceptos de lenguajes anteriores. Por ejemplo, de Simula67 ( 0.Iw1) y Algol68 ( Stroustrup 1987), para lo bueno y para lo malo [1], el lenguaje C++ incorpora muchas características heredadas del C, su ancestro más directo, el cual recoge a su vez influencias anteriores: B, BCPL ( 0.Iw2), etc. ( K&R).

Nota:  es mucho lo que puede encontrarse en la red sobre los orígenes del C y sus influencias previas, pero uno de los mejores documentos, con la autoridad que le confiere ser precisamente de uno de sus creadores, es:  "The development of the C language"  (  Dennis M. Ritchie).

Para los que estudian C++ como una herramienta de trabajo, aunque en realidad su profesión no es la informática, sino otra más "científica", una advertencia: como todos los lenguajes de programación (obra de los últimos cinco segundos de la evolución del hombre), C++ es muy "artificial", y aunque los informáticos son gente bastante lógica, las cosas son así porque sí.  No se le puede pedir el tipo de lógica que encontramos en las Matemáticas o en la Física por ejemplo.

El resultado de todo esto es que C++ está repleto de conceptos y detalles inter-relacionados; reglas que son así por "definición"; porque a su inventor le pareció que eran la mejor forma de hacerlas o porque vienen heredadas [3].  Cuestiones que podrían quizás ser de otro modo, pero son así por compatibilidad (con el C); otras reglas tienen sus excepciones también por tradición o por herencia; etc.  Para el común de los mortales es imposible hacerse una idea exacta con una primera lectura, pues muchos conceptos solo cobran su verdadera dimensión cuando se entienden otros a los que no se ha llegado todavía [1a].

Hace tiempo leí sobre un personaje histórico del que decían que tenía tal capacidad, que leía los libros por el sistema de ir arrancando y tirando las páginas leídas.  Desde luego no es el caso del C++; es más que posible que cualquier libro de C++ requiera múltiples relecturas, cada una de las cuales nos proporcionará una mejor y más detallada perspectiva del lenguaje, de sus enormes posibilidades e incluso de los niveles de refinamiento y sofisticación que pueden alcanzarse con él [2].  El propio inventor del lenguaje afirma al respecto:  "Don't panic!.  All will become clear in time" [2a].

Se me ocurre que una buena analogía serían esas imágenes Web que aparecen progresivamente y que solo se ven con nitidez cuando se ha terminado su descarga [4].  Las referencias a otros puntos hace que constantemente tengamos que saltar de un sitio a otro (por fortuna los documentos HTML y el navegador vienen que ni pintados para el caso, podemos saltar a una cita y volver inmediatamente el punto de partida con un par de clic de ratón).

Está fuera de toda duda que C++ es un lenguaje difícil y áspero;  podríamos citar al menos una decena de "lindezas" que se han dicho acerca de él (hemos incluido aquí alguna con objeto de que el estudiante sepa a que se enfrenta).  Sin embargo, nuestro ánimo no es disuasorio sino todo lo contrario;  considere que simplemente debe dedicarle una especial atención y esfuerzo, en la seguridad de que el lenguaje lo merece.  Tengo un amigo al que le gusta decir que hay dos clases de "informáticos":  Los que saben C++ y los que no merecen llamarse informáticos.  Seguramente es exagerado, pero estoy convencido que su estudio constituye la base de la informática actual.  Su rastro puede verse por doquier, incluso en lenguajes tan de moda y actuales como Java, php o JavaScript.  De forma que su conocimiento le da al estudiante no ocasional de informática una inmejorable posición de partida para adentrarse en otras materias.  En mi opinión el estudio de C++ en las Escuelas de Informática sería comparable al estudio de anatomía en las de Medicina.

Seguramente necesitará bastantes horas para llegar a dominar C++, pero es con diferencia "El Rey" de los lenguajes de programación.  Habrá merecido la pena!.

§2  El C++ real y el C++ Estándar

Al hablar de lenguajes no privados [5] tan universales como C++, es un Comité Internacional el que decide como es (o debe ser) el lenguaje ( E1[2]). Posteriormente los fabricantes de compiladores intentan adecuar sus productos a las directrices del Estándar, aunque en ocasiones incluyen por su cuenta características y funcionalidades específicas (principalmente en las librerías que acompañan al compilador en forma de herramientas). Esto significa que existen tantas versiones de C++ como plataformas distintas, ya que existen compiladores C++ para virtualmente cada combinación de hardware y Sistema Operativo conocidos.

Las diferencias entre estos C++ reales y el C++ Estándar (o de Stroustrup) como lo denominó algún autor [6], es por supuesto variable en función del grado de adecuación que haya logrado cada fabricante. Además, el Estándar es bastante tolerante y permite a los implementadores decidir por su cuenta ciertas cuestiones de detalle. Todos estos factores hacen que en ocasiones, dos compiladores distintos aplicados al mismo código conduzcan a resultados diferentes. Por supuesto, no nos referimos a que 2 + 2 dejen de ser 4, sino a errores y avisos de cosas que son o no permitidas en según qué plataforma.

A las consideraciones anteriores hay que añadir que los ordenadores son finitos, lo que exige que las aplicaciones que corren en ellos sean necesariamente finitas.  En consecuencia, los fabricantes de compiladores se ven obligados a imponer ciertas condiciones y límites a sus productos.  Por ejemplo:  el Estándar dice que los bloques, zonas de programa englobadas en llaves { }, pueden ser anidados (bloques dentro de otros bloques).  Sin embargo las implementaciones pueden señalar un límite máximo de anidamiento para estos casos.  Naturalmente los límites y condiciones pueden variar para cada compilador.  El Estándar solo exige que estas limitaciones estén debidamente documentadas.

Nota:  En esta obra hemos utilizado los tres compiladores C++ de uso más popular en el mundo de la informática personal y empresarial:  El compilador Borland C++ de Imprise.  El Visual C++ de Microsoft, y el C++ de la Open Software Foundation (GNU Cpp).  Los dos primeros son para la plataforma Wintel.  El último para Linux.  Desafortunadamente, la versión que dispongo de "Visual" es bastante antigua (1998).

Como comprobará el lector a lo largo de estas páginas, aunque por fortuna los tres compiladores son bastante consistentes y se aproximan al Estándar, esta concordancia no siempre es perfecta y los resultados no siempre coinciden en algunos rincones del lenguaje.  En aquellas ocasiones en que hemos detectado disparidades se han incluido las observaciones pertinentes.  Tenga en cuenta que estas se refieren siempre a versiones concretas de cada compilador y que las divergencias pueden o no manifestarse si se utilizan otros compiladores u otras versiones.


Tanto si se va a acometer un nuevo proyecto, como si se debe mantener el código de aplicaciones ya existentes (que los anglosajones denominan "legacy code"), es importante tener claras algunas cuestiones relativas a la estandarización de lenguaje y al grado de adaptación de cada plataforma o compilador concreto. Estas cuestiones aparecen con cierta regularidad en los foros de debate, y aunque no conciernen estrictamente a neófito, en cambio sí son importantes para el profesional que se enfrenta a situaciones del mundo real. Son las siguientes:

§2.1  Adecuación al Estándar

Observe "el Estándar" no incluye ningún código; es una mera descripción de cómo deben ser las cosas y que el código está en la interpretación que cada fabricante (compilador) hace de las recomendaciones anteriores. Observe también, que la declaración de que un compilador o plataforma de desarrollo "sigue el Estándar", solo indica que la parte cuyo comportamiento está definido en la norma, se comporta exactamente según lo indicado por esta, pero que lo anterior no es óbice para que pueda contener extensiones específicas (no estándar), ni para que carezca de todas las características especificadas en la norma (lo que se denomina "100% conforme). Algunas funcionalidades sencillamente pueden faltar (no estar implementadas).

Nota: en general las deficiencias o carencias se refieren a las partes más modernas del lenguaje. Especialmente algunos aspectos del tratamiento de clases y funciones genéricas ("templates").  En el momento de actualizar esta página (Diciembre 2006), solo un compilador que conozca, presume de ser 100% "compliant"; el resto presenta diverso grado de adecuación. Desde las muy bajas, como son proverbialmente las antiguas versiones de Microsoft VC++, hasta las modernas, en las que es del orden del 99%.  De acuerdo con los expertos, los compiladores más conformes por el momento son: la serie GNU c++ 4*; VC 2k3; VC 2k5; Intel C++ 8.0 y Comeau 4.2 (o versiones posteriores).

Salvo casos de fuerza mayor, que se deba lidiar con "legacy code", el consejo de los expertos es no considerar siquiera cualquier compilador cuyo fabricante no lo haya actualizado en los últimos cuatro años.

§2.2  Importancia de escribir código estrictamente estándar

La cuestión es totalmente independiente de la anterior, aunque su planteamiento carece de sentido en el supuesto de que utilicemos un compilador que carece de extensiones particulares y sigue el estándar al 100%.

Las posturas "relajadas" a este respecto se sintetizan en que debe primarse la rapidez en la puesta apunto de la aplicación. Sus defensores argumentan que les importa más completar rápidamente las aplicaciones, que la pureza conceptual o formal de su código, y que a sus clientes solo les importa el precio final de las mismas. En consecuencia, debe utilizarse sin escrúpulo cualquier característica o recurso disponible en la plataforma.  Las posturas estrictas argumentan que el costo de mantenimiento de las aplicaciones es tanto o más importante que el de su desarrollo inicial, y que en consecuencia, debe seguirse escrupulosamente el Estándar. Sobre todo, teniendo en mente la posibilidad de que el usuario pueda migrar a otra plataforma en el futuro. En cuyo caso, la fidelidad al estándar pagará sus réditos.  Las posturas extremas preconizan incluso utilizar solo aquel subconjunto del Estándar que sea universalmente soportado, intentando huir de "rincones oscuros" cuyo comportamiento exacto dependa del compilador.

§3  Organización y plan de la obra

La propia naturaleza del lenguaje y las, ya señaladas, complejas inter-ralaciones entre sus partes, hacen que en principio sea difícil establecer un orden de exposición, un "Plan de la obra"  que diríamos.  En este caso el "Plan" no ha existido en absoluto, como se indicó en el prólogo, comencé aproximadamente con el mismo orden que en "C++ Builder Languaje Guide", al que se han ido haciendo retoques.

De todas formas, sea cual sea el plan de la obra, inevitablemente aparecerán cuestiones para las que seguir su hilo argumental requerirá un proceso de saltos de un sitio a otro, puesto que si se encadena la exposición siguiendo un orden conceptual determinado, otros conceptos vendrán inevitablemente desordenados.  Parece ser que la naturaleza del conocimiento es más bien una suerte de inter-relaciones más parecidas a las redes neuronales que a una cinta de casete.  A lo largo de estas páginas me ha venido a la mente muchas veces lo desesperante que debe ser preparar un proyecto docente para esta asignatura que no pueda ser fácilmente discutido.

En cualquier caso, la lectura de libros electrónicos como el presente (al menos para mi) presentan un cierto problema. No aparecen los capítulos uno detrás de otro como en los libros clásicos "en papel", en los que hay un orden "natural"; un principio organización posicional y de orden de lectura. La ubicuidad del texto electrónico resulta molesta en cierto sentido. Tengo que reconocer que no estoy demasiado satisfecho de la "navegabilidad" en el formato actual, lo que no significa que no sea cómodo saltar de un sitio a otro (esto me pasa en general con todos los sistemas de ayuda on-line). Si eres de los que prefieren tener la idea de un cierto orden, te aconsejo que utilices el Índice; está a una distancia de un solo clic de ratón de cualquier página en que te encuentres: [Indice] en la esquina superior derecha.

  Inicio.


[1]  Respecto a esta influencia, hay opiniones para todos los gustos. En el enlace adjunto puede encontrar una de ellas, "Why C++ Sucks" (en inglés). Originalmente el documento estaba en   http://world.std.com/, sin embargo, a mediados de 2006 un lector me avisó que el enlace estaba roto. No he podido volver a encontrar el documento original (parece como si se lo hubiese tragado la red). Sin embargo, afortunadamente conservo una copia en mi archivo histórico Why C++ Sucks.

[1a] "Then there are the many hidden features in C++ that you cannot reveal up front"...  "There is a lot to learn after you learn the language. First you solo. Then you get your pilot's license.  Then you learn how to fly.  Learning C++ is a process of discovery".  Al Stevens  "C. Programming".  Dr. Dobb's Journal.  Sept. 1992.   

[2]  Es frecuente que encontremos trozos de código elegantísimos pero también difíciles de desentrañar en una primera lectura.  Como botón de muestra, las dos sentencias que siguen son perfectamente correctas en c++:

int z = *pt3+-*++pt3;

void (_USERENTRY * _RTLENTRY _EXPFUNC32 signal(int __sig, void (_USERENTRY * __func)(int))) (int);

[2a]  Stroustrup TC++PL  §2.9 [1]

[3]  Los comités de estandarización también tienen mucho que decir al respecto, de forma que la versión "Estándar" de cualquier lenguaje es algo que se escapa de las manos y del control de su creador inicial.

[4]  Son las imágenes GIF entrelazadas o las JPEG progresivas.

[5]  "Not proprietary" que no son propiedad intelectual de ninguna empresa o institución.  De esta forma no existe un único "fabricante" del lenguaje que decide sus características.  En caso contrario, por ejemplo el de Java, propiedad de la compañía SUN, es esta última la que controla su desarrollo.

[6]  Desde su alumbramiento, el Dr. Stroustrup ha seguido muy de cerca la evolución y desarrollo de su "criatura", aunque desde luego, actualmente la última palabra la tiene el comité encargado de elaborar el Estándar al que él mismo pertenece.