Resumen C++

Tipos básicos

Strings

En C++ se requiere la inclusión de la biblioteca «<string>» para poder hacer uso de ellos en el «namespace std«.

Comparar strings

Se comparan los strings con el operador «==».

Arrays

– Declaración, acceso, concatenación

WIP

Punteros y referencias

//Declarar puntero
int* puntero_a_entero;

//Obtener dirección de memoria de variable (referencia)
int entero;
puntero_a_entero = &entero;

//Obtener el valor al que apunta un puntero
int entero = *puntero_a_entero;

Como norma general para saber si se debe usar un puntero o una referencia:

  • Las referencias se usan para devolver valores en un parámetro de salida en una función.
  • Los punteros se usan para implementar algoritmos y estructuras de datos.

Existen los «smart pointers» para facilitar el manejo de punteros y evitar «memory leaks».

Smart pointers

Unique pointer

Se borra el contenido del puntero automáticamente al salir del ámbito del puntero.

#include <memory>
int main(){
  {
    // Dos formas de instanciar:
    std::unique_ptr <CMiClase> miObjeto = std::make_unique <CMiClase>();
    // ó
    std::unique_ptr <CMiClase> miObjeto(new CMiClase());
  }
  // Aquí ya no existe el puntero ni el contenido del mismo
}

Shared pointer

Puntero pensado para utilizarlo en otros ámbitos, compartirlo para otras funciones, objetos, etc. Tiene un contador interno que indica el número de referencias que existen del puntero y al llegar a 0 el contenido de la memoria se libera.

#include <memory>
int main(){
  std::shared_ptr <CMiClase> puntero2;
  {
    // Se debe instanciar así:
    std::shared_ptr <CMiClase> miObjeto = std::make_shared <CMiClase>();
    
    // Este segundo método es ineficaz al tener que crear dos referencias 
    // en bloques diferentes de memoria
    std::shared_ptr <CMiClase> miObjeto(new CMiClase());

    //Se puede copiar el puntero
    puntero2 = miObjeto;
  }
}

Weak pointer

Se utiliza para copiar la referencia de un «shared pointer» sin que este último incremente su contador de referencias.

#include <memory>
int main(){
  std::weak_ptr<CMiClase> puntero2;
  {
    std::shared_ptr <CMiClase> miObjeto = std::make_shared <CMiClase>();
    puntero2 = miObjeto;
  }
}

 

TADs comunes

WIP

TAD = Tipo Abstracto de dato.

Mapa

Lista

Lista enlazada

Lista doblemente enlazada

Pila

Cola

Sentencias de control

foreach

vector<UnaClase> vectorDeObjetos;
//...
for (auto objeto : vectorDeObjetos) {
  // objeto es de tipo UnaClase;
  objeto->funcionX();
}

 

Imports/includes

Sintaxis
#include "stdafx.h"
#include <iostream>
Referencias cíclicas

Las referencias cíclicas (circular dependency) son aquellas en las que una clase A incluye (include) a una clase B y esta, a su vez, incluye (include) otra vez a la clase A. Esto provocará que el compilador intente preparar suficiente memoria para cada clase de forma infinita y generará un error de complicación.

En esos casos hay que:

1.- Separar por completo la definición de la implementación de la clase en los archivos .h y .cpp respectivamente (Aunque esta debería ser tu práctica habitual para definir clases).

2.- En la definición de la clase B (B.h) no incluir a la clase A pero avisar al compilador de la existencia de la clase A (forward declaration):

//B.h
#pragma once

//#include "A.h"
class A; //forward declaration

class B{
  //..
}

3.- En la implementación de la clase B (B.cpp) incluir a la clase A:

//B.cpp
#include "A.h"
#include "B.h"

//..
Bibliotecas útiles
  • <iostream>: para entrada y salida en la ventana de la consola con «cout» y «cin«
  • <string>: para el uso de strings
  • <vector>: para el uso de listas
  • <map>: para el uso de listas asociativas
  • <boost>: compendio de bibliotecas externas (requiere inclusión explícita).
  • <memory>: para utilizar punteros inteligentes

Funciones

WIP

Declaración

Parámetros de entrada (IN)

Parámetros de salida (OUT)

Parámetro por copia

Parámetro por referencia

Parámetros opcionales

Parámetros por defecto

Funciones estáticas

//Definición
class CClase{
public:
  static int metodoEstatico(/*Parámetros*/);
  //...
}

//Uso
CClase::metodoEstatico(/*Parámetros*/);

Funciones virtuales

virtual void metodoVirtual(/*Parametros*/) = 0;

Salida por pantalla

Mostrar texto en consola

#include <iostream>

int variable = 1;
cout << "Texto" << variable << endl;

Mostrar error

WIP

Mostrar ventana informativa

WIP

Volcar el estado de una variable

WIP

Objetos

Declaración (Clases)

En el archivo header (de extensión «.h») se sigue la estructura:

//HEADER
#pragma once
class CMiClase
{
public:
  CMiClase(); //Constructor
  void functionSinRetorno();
  //Getter declarado y definido en el propio header en una sola línea (inline)
  inline int getValor(){ return valor; }; 
  ~CMiClase(); //Destructor
private:
  int valor;
protected:
//...
};

En el archivo CPP se tienen que definir los métodos de la clase con la siguiente sintaxis:

//CPP
#include "CMiClase.h"
void CMiClase::funcionSinRetorno(){
  // Haz cosas aquí
}
Instanciación, uso y destrucción

Se puede instanciar automática o dinámicamente.

Automáticamente: no es un puntero, el espacio en memoria se determina en tiempo de compilación no de ejecución, no requiere tener en cuenta la destrucción del objeto ni de sus atributos, se destruye automáticamente al salir del ámbito (scope) de la variable.

CMiClase miObjeto;
// Se usa la notación punto para los 
// objetos que no son punteros
miObjeto.metodo();

Dinámicamente: la memoria que usa el objeto se asigna en tiempo de ejecución, requiere tener en cuenta la destrucción del objeto y de sus atributos. El puntero se destruye automáticamente al salir del ámbito de la variable puntero, pero no se libera la memoria a la que este apunta; puede provocar «memory leaks» si no se maneja adecuadamente.

//Se debe declarar como un puntero
CMiClase* miObjeto = new CMiClase();
//Se usa la notación flecha para acceder a sus atributos
miObjeto->metodo();
//Se destruye con delete
delete miObjeto;

Se pueden utilizar punteros inteligentes (smart pointers) para evitar problemas en el uso y destrucción de punteros.

Copia

Herencia en objetos

Sintaxis

En el archivo header (de extensión «.h») se sigue la estructura:

#pragma once
#include "CClasePadre.h"
class CClaseHija : public CClasePadre
{
  // También tenemos aquí (de forma implícita) los  
  // atributos del padre que sean "public" o "protected"
  int atributoHija;
public:
  CClaseHija();
  // Sólo se tienen que volver a declarar las 
  // funciones heredadas que deseamos redefinir
  float funcionPadreRedefinida(); 
  ~CClaseHija();
private:
//...
};

En el archivo CPP se tienen que definir el constructor que llame a la clase padre, el resto de funciones se implementan igual:

#include "CClaseHija.h"

// Así se llama al constructor de la súper-clase
CClaseHija::CClaseHija() : CClasePadre()
{
  //...
}

float CClaseHija::funcionPadreRedefinida(){
  //...
}
Llamada a super-clase

WIP

Herencia múltiple

Se indican las clases de las que se heredan separadas con comas en un orden concreto (cuál?)

class Hija : public Clase1, Clase2
{
  //...
}

Interfaces

Definición

No hay interfaces en C++, se hace uso de de métodos virtuales para su definición y la herencia múltiple para su implementación.

Enumerados

Definición

WIP

Uso

WIP

Comparación

WIP

Excepciones

Lanzar excepción
throw runtime_error("blabla");
Capturar excepción
try {
  //método que lanza runtime_error
}
catch (runtime_error err) {
  cerr << err.what() << endl;
}
// No existe sentencia "finally"
Capturar multiples excepciones

WIP

Mostrar el StackTrace

En C++ no se puede mostrar (por limitaciones del lenguaje), pero se puede hacer uso de las macros del compilador como «__FILE__» y «__LINE__» a la hora de lanzar una excepción para indicar en el mensaje de la excepción dónde ha sido lanzada.

Definir excepción

WIP

Ficheros de texto

Read

WIP

Write

WIP

Append

WIP

Deja un comentario