Introducción
Nociones clave
1. Principales características del lenguaje C++
El lenguaje C++ apareció oficialmente en 1983, fecha en que se utilizó por primera vez fuera del laboratorio de AT&T que lo creó. Su diseñador, Bjarne Stroustrup, había comenzado su trabajo varios años antes, probablemente alrededor de 1980. El lenguaje C++, hasta ese momento llamado "C con clases", se desarrolló conservando la mayoría de los conceptos del lenguaje C, su predecesor. Luego, los dos idiomas intercambiaron conceptos entre sí.
Como el lenguaje C, C++ adopta una visión muy cercana a la máquina. Estaba destinado principalmente a la escritura de sistemas operativos, pero sus características aportaron otras perspectivas.
El lenguaje está compuesto por instrucciones cortas y muy explícitas, cuyo tiempo de ejecución se puede prever de antemano, cuando se escribe el programa.
Siendo deliberadamente limitado el número de instrucciones y notaciones, las interpretaciones de las construcciones semánticas son múltiples y esto es, sin duda, lo que el diseñador del lenguaje C++ designa bajo el término de expresividad.
Sin embargo, Bjarne Stroustrup tuvo la prudencia de sortear ciertos escollos del lenguaje C, y en particular su tendencia a reducirlo todo al nivel de bytes, una cantidad digital limitada y totalmente obsoleta en la historia de la informática, incluso en 1980. Para obtener este resultado, el lenguaje se enriqueció con clases que describen tipos de datos adaptados a las diferentes necesidades del programador. La visibilidad del lenguaje, combinada con la abstracción de las clases proporciona programas de alto nivel.
Las clases (y la programación orientada a objetos), no se inventaron con C++. El inventor del lenguaje se esforzó por adaptar conceptos de alto nivel introducidos por el lenguaje Simula en 1967, a una plataforma muy explícita, el lenguaje C.
El resultado de esta doble unión es un lenguaje muy rico y potente, particularmente expresivo y al mismo tiempo muy efectivo. Posteriormente, el lenguaje se refinó, sufrió evoluciones y transformaciones, hasta la etapa en que el producto de laboratorio se convirtió en un estándar, etiquetado por la organización estadounidense ANSI. El trabajo de normalización comenzó...
Bases de la programación C++
Ahora vamos a descubrir cómo C++ permite implementar algoritmos. Este lenguaje pertenece a la familia de los lenguajes procedimentales, lo que significa que las instrucciones de un programa se agrupan para formar procedimientos, que también se denominan funciones.
Un programa en C++ utiliza, por un lado, variables para almacenar valores y, por otro, instrucciones para cambiar estos valores. Este no es el aspecto más original de C++ ya que comparte esta base "algorítmica" con el lenguaje C. Como resultado, muchos tipos de datos son comunes a ambos lenguajes y las instrucciones básicas también son idénticas. Esto facilita el aprendizaje del lenguaje C++ y mejora la portabilidad ascendente.
Tenga en cuenta también que la sintaxis de C++ es un poco más flexible que la de C, especialmente en lo que respecta a la declaración de variables y parámetros. La relectura de los programas se mejora de manera natural.
Para el lector que descubre la programación orientada a objetos con C++, es fundamental asimilar por completo la programación funcional, es decir, basada en funciones. Conocer los algoritmos básicos (búsquedas u ordenaciones), es una muy buena forma de hacerlo. La programación orientada a objetos es un superconjunto de la programación funcional, una forma particular de estructurarla y explotarla. Pero las reglas básicas siguen siendo las mismas.
Antes de cualquier instrucción o declaración de variable, explicamos la notación de los comentarios.
Los comentarios son anotaciones escritas por el programador. Facilitan la relectura y en ocasiones, recuerdan el papel de determinadas variables o bloques de instrucciones.
El lenguaje C++ tiene dos tipos de comentarios: los comentarios en una sola línea y los que ocupan varias líneas.
Para el primer tipo, usamos la barra doble. El compilador que encuentra esta secuencia // ignora todo lo que sigue hasta el final de la línea.
El segundo tipo está delimitado por las secuencias /* y */, lo que permite la anotación en varias líneas o solo en una parte de la línea, como en lenguaje C. Atención, el uso de comentarios anidados /*....../*...*/......*/ no siempre es aceptado por el compilador.
Los comentarios se pueden colocar en cualquier archivo fuente...
Excepciones
1. Los enfoques de bajo nivel
Cualquier programa está sujeto a los caprichos del entorno que lo hace funcionar. Puede haber fallos de hardware, algunos procesos bloquean recursos críticos, la memoria no es inagotable, etc.
Para que un programa entre en la categoría de software, debe ser tolerante con estos eventos y no bloquearse o peor aún, terminar abruptamente.
Los lenguajes de programación más antiguos generalmente están mal equipados para lidiar con situaciones problemáticas. A menudo, los desarrolladores han confiado en los dispositivos proporcionados por su entorno.
a. Banderas e interrupciones
Algunos microprocesadores tienen instrucciones destinadas a activar subrutinas (funciones en lenguaje C) cuando se cumplen ciertas condiciones: una división por cero, un desbordamiento de la capacidad, un fallo en la gestión de la memoria paginada, etc. No es raro ver cómo algunas de estas interrupciones quedan bajo el entendimiento del programador del sistema. Por ejemplo, el sistema operativo MS-DOS programó la interrupción n.º 19 para reiniciar el sistema. Hay controladores de dispositivos que utilizan estas interrupciones para sincronizar los intercambios de datos. Estos incluyen controladores de pantalla y disco duro, y controladores que admiten tarjetas de captura digital o las tarjetas de sonido.
Usando las instrucciones apropiadas, que se pueden simbolizar llamando a una función de API puesta a disposición por el sistema operativo, el programa registra la dirección de una función llamada callback para un número de interrupción dado.
Entonces, esta interrupción se puede activar directamente por el microprocesador(en caso de división por cero, por ejemplo) o por un programa. Cuando se activa la interrupción, el microprocesador llama automáticamente a la función callback. Cuando un programa está en el origen de la activación de la interrupción, hablamos de una interrupción de software.
Sin embargo, las interrupciones no son una forma suficientemente general para el tratamiento de los errores. Para empezar, no todos los microprocesadores están equipados con este dispositivo. Por otro lado, la única tabla de interrupciones la gestiona el sistema. Finalmente, algunas interrupciones se deben activar con mayor...
Trabajos prácticos
1. Control del intérprete tiny-lisp
El código fuente del intérprete tiny-lisp se estudia a lo largo del libro. Unas pocas docenas de líneas de C++ son suficientes para analizar y evaluar expresiones basadas en la sintaxis LISP.
En los próximos trabajos prácticos, descubriremos la estructura del proyecto de C++ tiny-lisp, antes de que lo hagamos funcionar de dos maneras. El primer enfoque es una aplicación de consola capaz de cargar y ejecutar scripts. El segundo método ejecuta el intérprete tiny-lisp desde un editor de scripts con ventana.
a. Estructura de la solución
Después de descargar los archivos complementarios de este libro, abra en Visual Studio la solución tiny-lisp.sln que consta de tres proyectos:
-
El proyecto C++ tiny-lisp, que incluye el código del intérprete.
-
El proyecto C# tinylisplab, que incluye el código para el editor de código fuente tiny-lisp.
-
El proyecto C# WinFormsSyntaxHighlighter, que incluye extensiones para aplicar la coloración sintáctica para el componente RichTextBox.
Nos vamos a centrar en el proyecto tiny-lisp de C++ y presentaremos las carpetas principales (también llamadas "filtros" en Visual Studio).
b. La carpeta config
La mayor parte del código está organizado como clases de C++, descritas en archivos de encabezado .h y archivos fuente .cpp.
La carpeta config incluye la clase Configuration, utilizada para habilitar módulos de extensión para el lenguaje tiny-lisp.
c. La carpeta framework
La carpeta framework incluye varias clases de herramientas para administrar colores, archivos o la comunicación entre objetos.
d. La carpeta jsonlib
El formato JSON (JavaScript Object Notation) tiende a sustituir a XML; la carpeta jsonlib incluye una adaptación del código json11 para convertir objetos C++ en flujo JSON y viceversa.
e. La carpeta language
Es un poco el núcleo del intérprete tiny-lisp, esta carpeta contiene la mayoría de las clases C++ del proyecto. Los archivos principales son type.h, que contiene las clases Variant y Environment, así como Parser.h/Parser.cpp.
El analizador de expresiones (parser en inglés) LISP, es responsable de dividir las cadenas de caracteres (string) en instrucciones y encontrar su significado.