Empezando con C ++

Download c++ eBook

Observaciones

El programa 'Hello World' es un ejemplo común que se puede usar simplemente para verificar la presencia del compilador y la biblioteca. Utiliza la biblioteca estándar de C ++, con std::cout de <iostream> , y solo tiene que compilar un archivo, lo que minimiza la posibilidad de un error de usuario durante la compilación.


El proceso para compilar un programa C ++ difiere inherentemente entre compiladores y sistemas operativos. El tema Compilación y creación contiene los detalles sobre cómo compilar el código C ++ en diferentes plataformas para una variedad de compiladores.

Versiones

Versión Estándar Fecha de lanzamiento
C ++ 98 ISO / IEC 14882: 1998 1998-09-01
C ++ 03 ISO / IEC 14882: 2003 2003-10-16
C ++ 11 ISO / IEC 14882: 2011 2011-09-01
C ++ 14 ISO / IEC 14882: 2014 2014-12-15
C ++ 17 TBD 2017-01-01
C ++ 20 TBD 2020-01-01

Hola Mundo

Este programa imprime Hello World! al flujo de salida estándar:

std::cout << "Hello World!\n";
 

Véalo en vivo en Coliru .

Análisis

Examinemos cada parte de este código en detalle:

  • #include <iostream> es una directiva de preprocesador que incluye el contenido del archivo de cabecera estándar de C ++ iostream .

    iostream es un archivo de encabezado de biblioteca estándar que contiene definiciones de los flujos de entrada y salida estándar. Estas definiciones se incluyen en el std nombres std , que se explica a continuación.

    Los flujos de entrada / salida (E / S) estándar proporcionan formas para que los programas obtengan entrada y salgan a un sistema externo, generalmente el terminal.

  • int main() { ... } define una nueva función llamada main . Por convención, la función main se llama a la ejecución del programa. Sólo debe haber una función main en un programa de C ++, y siempre debe devolver un número del tipo int .

    Aquí, el int es lo que se llama el tipo de retorno de la función. El valor devuelto por la función main es un código de salida.

    Por convención, un sistema que ejecuta el programa interpreta como exitoso un código de salida del programa 0 o EXIT_SUCCESS . Cualquier otro código de retorno está asociado con un error.

    Si no hay ninguna declaración de return , la función main (y, por lo tanto, el propio programa) devuelve 0 de forma predeterminada. En este ejemplo, no necesitamos escribir explícitamente la return 0; .

    Todas las demás funciones, excepto aquellas que devuelven el tipo void , deben devolver explícitamente un valor de acuerdo con su tipo de retorno, o de lo contrario no deben devolverlo en absoluto.

  • std::cout << "Hello World!" << std::endl; grabados "¡Hola mundo!" al flujo de salida estándar:

    • std es un espacio de nombres , y :: es el operador de resolución de alcance que permite buscar objetos por nombre dentro de un espacio de nombres.

      Hay muchos espacios de nombres. Aquí, usamos :: para mostrar que queremos usar cout desde el std nombres std . Para obtener más información, consulte Operador de resolución de alcance - Documentación de Microsoft .

    • std::cout es el objeto de flujo de salida estándar , definido en iostream , y se imprime en la salida estándar ( stdout ).

    • << es, en este contexto , el operador de inserción de flujo , llamado así porque inserta un objeto en el objeto de flujo .

      La biblioteca estándar define el operador << para realizar la inserción de datos para ciertos tipos de datos en flujos de salida. stream << content inserta el content en el flujo y devuelve lo mismo, pero el flujo actualizado. Esto permite encadenar inserciones de secuencias: std::cout << "Foo" << " Bar"; Imprime "FooBar" en la consola.

    • "Hello World!" es una cadena de caracteres literal , o un "texto literal". El operador de inserción de flujo para los literales de cadena de caracteres se define en el archivo iostream .

    • std::endl es un objeto especial de manipulador de flujo de E / S , también definido en el archivo iostream . Insertar un manipulador en un flujo cambia el estado del flujo.

      El manipulador de flujo std::endl hace dos cosas: primero inserta el carácter de fin de línea y luego vacía el búfer del flujo para forzar que el texto aparezca en la consola. Esto asegura que los datos insertados en la transmisión realmente aparezcan en su consola. (Los datos de transmisión generalmente se almacenan en un búfer y luego se "descargan" en lotes, a menos que se fuerce un vaciado de inmediato).

      Un método alternativo que evita la descarga es:

      #include <iostream>
      
      int main()
      {
          std::cout << "Hello World!" << std::endl;
      }
       

      donde \n es la secuencia de escape de caracteres para el carácter de nueva línea.

    • El punto y coma ( ; ) notifica al compilador que una declaración ha finalizado. Todas las declaraciones de C ++ y las definiciones de clase requieren un punto y coma finalizado.

Comentarios

Un comentario es una forma de colocar texto arbitrario dentro del código fuente sin que el compilador de C ++ lo interprete con un significado funcional. Los comentarios se utilizan para dar una idea del diseño o método de un programa.

Hay dos tipos de comentarios en C ++:

Comentarios de una sola línea

La secuencia de doble barra diagonal hacia adelante // marcará todo el texto hasta que aparezca una nueva línea como comentario:

int main()
{
   /*
    *  This is a block comment.
    */
   int a;
}
 

C-Style / Block Comentarios

La secuencia /* se usa para declarar el inicio del bloque de comentarios y la secuencia */ se usa para declarar el final del comentario. Todo el texto entre las secuencias de inicio y finalización se interpreta como un comentario, incluso si el texto es de otro modo una sintaxis de C ++ válida. Estos a veces se denominan comentarios de "estilo C", ya que esta sintaxis de comentario se hereda del lenguaje predecesor de C ++, C:

int main()
{
   /* A block comment with the symbol /*
      Note that the compiler is not affected by the second /*
      however, once the end-block-comment symbol is reached,
      the comment ends.
   */
   int a;
}
 

En cualquier comentario de bloque, puedes escribir lo que quieras. Cuando el compilador encuentra el símbolo */ , termina el comentario de bloque:

void SomeFunction(/* argument 1 */ int a, /* argument 2 */ int b);
 

El ejemplo anterior es un código válido de C ++ (y C). Sin embargo, tener /* adicional dentro de un comentario de bloque puede dar como resultado una advertencia en algunos compiladores.

Los comentarios en bloque también pueden comenzar y terminar dentro de una sola línea. Por ejemplo:

int main()
{
   // This is a single-line comment.
   int a;  // this also is a single-line comment
   int i;  // this is another single-line comment
}
 

Importancia de los comentarios

Al igual que con todos los lenguajes de programación, los comentarios proporcionan varios beneficios:

  • Documentación explícita de código para facilitar la lectura / mantenimiento
  • Explicación del propósito y funcionalidad del código.
  • Detalles sobre la historia o razonamiento detrás del código.
  • Colocación de derechos de autor / licencias, notas de proyectos, agradecimientos especiales, créditos de contribuyentes, etc. directamente en el código fuente.

Sin embargo, los comentarios también tienen sus desventajas:

  • Deben mantenerse para reflejar cualquier cambio en el código.
  • Los comentarios excesivos tienden a hacer que el código sea menos legible

La necesidad de comentarios se puede reducir escribiendo un código claro y autodocumentado. Un ejemplo simple es el uso de nombres explicativos para variables, funciones y tipos. Factorizar tareas relacionadas lógicamente en funciones discretas va de la mano con esto.

Marcadores de comentario utilizados para deshabilitar el código

Durante el desarrollo, los comentarios también se pueden usar para deshabilitar rápidamente partes del código sin borrarlo. A menudo, esto es útil para propósitos de prueba o depuración, pero no es un buen estilo para nada que no sean ediciones temporales. Esto a menudo se conoce como "comentar".

Del mismo modo, mantener las versiones antiguas de un fragmento de código en un comentario con fines de referencia es desagradable, ya que desordena los archivos al tiempo que ofrece poco valor en comparación con la exploración del historial del código a través de un sistema de versiones.

Función

Una función es una unidad de código que representa una secuencia de sentencias.

Las funciones pueden aceptar argumentos o valores y devolver un solo valor (o no). Para usar una función, una llamada de función se usa en valores de argumento y el uso de la llamada de función se reemplaza con su valor de retorno.

Cada función tiene una firma de tipo : los tipos de sus argumentos y el tipo de su tipo de retorno.

Las funciones están inspiradas en los conceptos del procedimiento y la función matemática.

  • Nota: las funciones de C ++ son esencialmente procedimientos y no siguen la definición exacta o las reglas de las funciones matemáticas.

Las funciones a menudo están destinadas a realizar una tarea específica. y puede ser llamado desde otras partes de un programa. Una función debe ser declarada y definida antes de ser llamada en otro lugar en un programa.

  • Nota: las definiciones de funciones populares pueden estar ocultas en otros archivos incluidos (a menudo por conveniencia y reutilización en muchos archivos). Este es un uso común de los archivos de encabezado.

Declaración de funciones

Una declaración de función declara la existencia de una función con su nombre y tipo de firma para el compilador. La sintaxis es la siguiente:

int add2(int); // Omitting the function arguments' name is also permitted.
 

En el ejemplo anterior, la función int add2(int i) declara lo siguiente al compilador:

  • El tipo de retorno es int .
  • El nombre de la función es add2 .
  • El número de argumentos a la función es 1:
    • El primer argumento es del tipo int .
    • El primer argumento se mencionará en el contenido de la función con el nombre i .

El nombre del argumento es opcional; La declaración para la función también podría ser la siguiente:

int add2(int i);  // The compiler will note that add2 is a function (int) -> int
int add2(int j);  // As add2 already has a definition of (int) -> int, the compiler
                  // will regard this as an error.
 

Según la regla de una definición , una función con un cierto tipo de firma solo se puede declarar o definir una vez en una base de código C ++ completa visible para el compilador de C ++. En otras palabras, las funciones con una firma de tipo específica no se pueden redefinir, solo deben definirse una vez. Por lo tanto, lo siguiente no es válido en C ++:

void do_something(); // The function takes no parameters, and does not return anything.
                     // Note that it can still affect variables it has access to.
 

Si una función no devuelve nada, su tipo de retorno se escribe como void . Si no toma parámetros, la lista de parámetros debe estar vacía.

#include <iostream>

int add2(int i);    // Declaration of add2

// Note: add2 is still missing a DEFINITION.
// Even though it doesn't appear directly in code,
// add2's definition may be LINKED in from another object file.

int main()
{
    std::cout << add2(2) << "\n";  // add2(2) will be evaluated at this point,
                                   // and the result is printed.
    return 0;  
}
 

Llamada de función

Una función puede ser llamada después de que haya sido declarada. Por ejemplo, el siguiente programa llama a add2 con el valor de 2 dentro de la función de main :

int add2(int i)       // Data that is passed into (int i) will be referred to by the name i
{                     // while in the function's curly brackets or "scope."
                    
    int j = i + 2;    // Definition of a variable j as the value of i+2.
    return j;         // Returning or, in essence, substitution of j for a function call to
                      // add2.
}
 

Aquí, add2(2) es la sintaxis de una llamada de función.

Definición de la función

Una definición de función * es similar a una declaración, excepto que también contiene el código que se ejecuta cuando se llama a la función dentro de su cuerpo.

Un ejemplo de una definición de función para add2 podría ser:

int add2(int i)           // Code contained in this definition will be evaluated
{                         // when add2() is called with one parameter.
    int j = i + 2;
    return j;
}

int add2(int i, int j)    // However, when add2() is called with two parameters, the
{                         // code from the initial declaration will be overloaded,
    int k = i + j + 2 ;   // and the code in this declaration will be evaluated
    return k;             // instead.
}
 

Sobrecarga de funciones

Puedes crear múltiples funciones con el mismo nombre pero diferentes parámetros.

int multiply(int a, int b = 7); // b has default value of 7.
int multiply(int a, int b)
{
    return a * b;               // If multiply() is called with one parameter, the
}                               // value will be multiplied by the default, 7.
 

Ambas funciones se llaman con el mismo nombre add2 , pero la función real que se llama depende directamente de la cantidad y el tipo de los parámetros en la llamada. En la mayoría de los casos, el compilador de C ++ puede calcular qué función llamar. En algunos casos, el tipo debe ser explícitamente establecido.

Parámetros predeterminados

Los valores predeterminados para los parámetros de función solo se pueden especificar en las declaraciones de función.

int multiply(int a = 10, int b = 20); // This is legal 
int multiply(int a = 10, int b);      // This is illegal since int a is in the former
 

En este ejemplo, se puede llamar a multiply() con uno o dos parámetros. Si solo se proporciona un parámetro, b tendrá un valor predeterminado de 7. Los argumentos predeterminados se deben colocar en los últimos argumentos de la función. Por ejemplo:

3+3
 

Llamadas de Funciones Especiales - Operadores

Existen llamadas a funciones especiales en C ++ que tienen una sintaxis diferente a name_of_function(value1, value2, value3) . El ejemplo más común es el de los operadores.

Ciertas secuencias de caracteres especiales que se reducirán a las llamadas de función del compilador, como ! , + , - , * , % y << y muchos más. Estos caracteres especiales se asocian normalmente con el uso no programado o se usan para la estética (por ejemplo, el carácter + se reconoce comúnmente como el símbolo de adición tanto en la programación en C ++ como en matemáticas elementales).

C ++ maneja estas secuencias de caracteres con una sintaxis especial; pero, en esencia, cada aparición de un operador se reduce a una llamada de función. Por ejemplo, la siguiente expresión en C ++:

operator+(3, 3)
 

es equivalente a la siguiente llamada de función:

int add2(int i); // The function is of the type (int) -> (int)
 

Todos los nombres de funciones del operador comienzan con el operator .

Mientras que en el predecesor inmediato de C ++, C, a los nombres de funciones de operador no se les pueden asignar diferentes significados al proporcionar definiciones adicionales con diferentes tipos de firmas, en C ++, esto es válido. "Ocultar" las definiciones de funciones adicionales bajo un nombre de función único se conoce como sobrecarga de operadores en C ++, y es una convención relativamente común, pero no universal, en C ++.

Preprocesador

El preprocesador es una parte importante del compilador.

Edita el código fuente, recorta algunos bits, cambia otros y agrega otras cosas.

En los archivos de origen, podemos incluir directivas de preprocesador. Estas directivas le indican al preprocesador que realice acciones específicas. Una directiva comienza con un # en una nueva línea. Ejemplo:

#include <something>
 

La primera directiva de preprocesador que encontrará es probablemente la

#include <iostream>
 

directiva. Lo que hace es toma todos something y lo inserta en el archivo de donde estaba la directiva. El programa hola mundo comienza con la línea.

#define something something_else
 

Esta línea agrega las funciones y objetos que le permiten usar la entrada y salida estándar.

El lenguaje C, que también utiliza el preprocesador, no tiene tantos archivos de encabezado como el lenguaje C ++, pero en C ++ puede usar todos los archivos de encabezado C.


La siguiente directiva importante es probablemente la

#if something==true
//code
#else
//more code
#endif

#ifdef thing_that_you_want_to_know_if_is_defined
//code
#endif
 

directiva. Esto le dice al preprocesador que a medida que avanza en el archivo, debe reemplazar cada ocurrencia de something con something_else . También puede hacer cosas similares a las funciones, pero eso probablemente cuenta como C ++ avanzado.

El something_else no es necesario, pero si se define something como nada, entonces fuera de las directivas de preprocesador, todas las apariciones de something se desvanecerá.

En realidad, esto es útil, debido a las #if , #else y #ifdef directivas. El formato para estos sería el siguiente:

#define ZERO 0
 

Estas directivas insertan el código que está en el bit verdadero y borran los bits falsos. Esto se puede usar para tener bits de código que solo se incluyen en ciertos sistemas operativos, sin tener que volver a escribir todo el código.

El proceso de compilación estándar de C ++.

El código del programa ejecutable de C ++ generalmente es producido por un compilador.

Un compilador es un programa que traduce código de un lenguaje de programación a otra forma que es (más) directamente ejecutable para una computadora. Usar un compilador para traducir código se llama compilación.

C ++ hereda la forma de su proceso de compilación de su lenguaje "principal", C. A continuación se muestra una lista que muestra los cuatro pasos principales de la compilación en C ++:

  1. El preprocesador de C ++ copia el contenido de cualquier archivo de encabezado incluido en el archivo de código fuente, genera un código de macro y reemplaza las constantes simbólicas definidas usando #define con sus valores.
  2. El archivo de código fuente expandido producido por el preprocesador C ++ se compila en lenguaje ensamblador apropiado para la plataforma.
  3. El código del ensamblador generado por el compilador se ensambla en el código de objeto apropiado para la plataforma.
  4. El archivo de código de objeto generado por el ensamblador está vinculado junto con los archivos de código de objeto para cualquier función de biblioteca utilizada para producir un archivo ejecutable.
  • Nota: algunos códigos compilados están vinculados entre sí, pero no para crear un programa final. Por lo general, este código "vinculado" también se puede empaquetar en un formato que puede ser usado por otros programas. Este "paquete de código empaquetado y utilizable" es lo que los programadores de C ++ denominan una biblioteca.

Muchos compiladores de C ++ también pueden combinar o deshacer ciertas partes del proceso de compilación para facilitar o para un análisis adicional. Muchos programadores de C ++ usarán diferentes herramientas, pero todas las herramientas generalmente seguirán este proceso generalizado cuando estén involucrados en la producción de un programa.

El siguiente enlace extiende esta discusión y proporciona un bonito gráfico para ayudar. [1]: http://faculty.cs.niu.edu/~mcmahon/CS241/Notes/compile.html

Visibilidad de prototipos y declaraciones de funciones.

En C ++, el código debe ser declarado o definido antes de su uso. Por ejemplo, lo siguiente produce un error de tiempo de compilación:

void foo(int x) {}  //Declare the foo function and body first

int main()
{
  foo(2); // OK: foo is completely defined beforehand, so it can be called here.
}
 

Hay dos formas de resolver esto: poner la definición o la declaración de foo() antes de su uso en main() . Aquí hay un ejemplo:

void foo(int);  // Prototype declaration of foo, seen by main
                // Must specify return type, name, and argument list types
int main()
{
  foo(2); // OK: foo is known, called even though its body is not yet defined
}

void foo(int x) //Must match the prototype
{
    // Define body of foo here
}
 

Sin embargo, también es posible "declarar hacia adelante" la función poniendo solo una declaración "prototipo" antes de su uso y luego definiendo el cuerpo de la función más adelante:

// foo.h
void foo(int); // prototype declaration
 

El prototipo debe especificar el tipo de retorno ( void ), el nombre de la función ( foo ) y los tipos de variables de la lista de argumentos ( int ), pero los nombres de los argumentos NO son necesarios .

Una forma común de integrar esto en la organización de los archivos de origen es hacer un archivo de encabezado que contenga todas las declaraciones de prototipo:

// foo.cpp --> foo.o
#include "foo.h" // foo's prototype declaration is "hidden" in here
void foo(int x) { } // foo's body definition
 

y luego proporcionar la definición completa en otro lugar:

// main.cpp --> main.o
#include "foo.h" // foo's prototype declaration is "hidden" in here
int main() { foo(2); } // foo is valid to call because its prototype declaration was beforehand.
// the prototype and body definitions of foo are linked through the object files
 

y luego, una vez compilado, vincule el archivo de objeto correspondiente foo.o al archivo de objeto compilado donde se usa en la fase de enlace, main.o :

int main()
{
  foo(2); // error: foo is called, but has not yet been declared
}

void foo(int x) // this later definition is not known in main
{
}
 

Se produce un error de "símbolo externo no resuelto" cuando existen la función prototipo y la llamada , pero el cuerpo de la función no está definido. Estos pueden ser más difíciles de resolver ya que el compilador no informará el error hasta la etapa final de vinculación, y no sabe a qué línea saltar en el código para mostrar el error.

Stats

9370 Contributors: 111
Wednesday, August 2, 2017
Licenciado bajo: CC-BY-SA

No afiliado a Stack Overflow
Rip Tutorial: info@zzzprojects.com

Descargar eBook