Académique Documents
Professionnel Documents
Culture Documents
C++ es un lenguaje de programación diseñado a media- ciendo al compilador que usaremos el espacio de nombres
dos de los años 1980 por Bjarne Stroustrup. La intención std por lo que no tendremos que incluirlo cuando usemos
de su creación fue el extender al exitoso lenguaje de pro- elementos de este espacio de nombres, como pueden ser
gramación C con mecanismos que permitan la manipula- los objetos cout y cin, que representan el flujo de salida
ción de objetos. En ese sentido, desde el punto de vista de estándar (típicamente la pantalla o una ventana de texto)
los lenguajes orientados a objetos, el C++ es un lenguaje y el flujo de entrada estándar (típicamente el teclado).
híbrido. La definición de funciones es igual que en C, salvo por la
Posteriormente se añadieron facilidades de programación característica de que si main no va a recoger argumentos,
genérica, que se sumó a los otros dos paradigmas que no tenemos por qué ponérselos, a diferencia de C, donde
ya estaban admitidos (programación estructurada y la había que ponerlos explícitamente, aunque no se fueran a
programación orientada a objetos). Por esto se suele decir
usar. Queda solo comentar que el símbolo << se conoce
que el C++ es un lenguaje de programación multiparadig- como operador de inserción, y grosso modo está envian-
ma. do a cout lo que queremos mostrar por pantalla para que
Actualmente existe un estándar, denominado ISO C++, lo pinte, en este caso la cadena “Hola mundo”. El mis-
al que se han adherido la mayoría de los fabricantes de mo operador << se puede usar varias veces en la misma
compiladores más modernos. Existen también algunos in- sentencia, de forma que gracias a esta característica po-
térpretes, tales como ROOT. dremos concatenar el objeto endl al final, cuyo resultado
será imprimir un retorno de línea.
Una particularidad del C++ es la posibilidad de redefi-
nir los operadores, y de poder crear nuevos tipos que se Por último tomaremos una secuencia de caracteres del
teclado hasta el retorno de línea (presionando ENTER),
comporten como tipos fundamentales.
llamando al método get del objeto cin.
El nombre C++ fue propuesto por Rick Mascitti en el año
1983, cuando el lenguaje fue utilizado por primera vez
fuera de un laboratorio científico. Antes se había usado
el nombre “C con clases”. En C++, la expresión “C++"
2 Tipos de datos
significa “incremento de C” y se refiere a que C++ es una
extensión de C. C++ tiene los siguientes tipos fundamentales:
1
2 2 TIPOS DE DATOS
• strcpy - wstrcpy
• std::string - std::wstring
• std::cout - std::wcout 2.4 La palabra “NULL”
Cabe resaltar que en C se define wchar_t como: Además de los valores que pueden tomar los tipos ante-
typedef unsigned short wchar_t; riormente mencionados, existe un valor llamado NULL,
sea el caso numérico para los enteros, caracter para el ti-
po char, cadena de texto para el tipo string, etc. El valor
Mientras que en C++ es en sí mismo un tipo de dato.
NULL, expresa, por lo regular, la representación de una
Macro, asignada al valor “0”.
2.3 La palabra reservada “void” Tenemos entonces que:
La palabra reservada void define en C++ el concepto de void* puntero = NULL; int entero = NULL; bool
no existencia o no atribución de un tipo en una variable boleana = NULL; char caracter = NULL;
o declaración. Es decir, una función declarada como void
no devolverá ningún valor. Esta palabra reservada tam- El valor de las variables anteriores nos daría 0. A diferen-
bién puede usarse para indicar que una función no recibe cia de la variable “caracter”, que nos daría el equivalente
parámetros, como en la siguiente declaración: a NULL, '\0', para caracteres.
4.1 Constructores 3
porcionaría uno predeterminado. Es necesario para ejecución del programa. La invocación del destructor de
la construcción de estructuras y contenedores de la un objeto que vive en heap se realiza a través del operador
STL. delete o delete[] para arrays. Ejemplo:
2. Constructor de copia. Es un constructor que reci- int main() { int *unEntero = new int(12); //asignamos
be un objeto de la misma clase, y realiza una copia un entero en memoria heap con el valor 12 int *array-
de los atributos del mismo. Al igual que el predeter- DeEnteros = new int[25]; //asignamos memoria para
minado, si no se define, el sistema proporciona uno. 25 enteros(no estan inicializados) delete unEntero;
//liberamos la memoria que ocupaba unEntero delete[]
3. Constructor de conversión. Este constructor, reci- arrayDeEnteros; //liberamos la memoria ocupada por
be como único parámetro, un objeto o variable de arrayDeEnteros return 0; }
otro tipo distinto al suyo propio. Es decir, convierte
un objeto de un tipo determinado a otro objeto del
Si no se utilizara el operador delete y delete[] en ese ca-
tipo que estamos generando.
so, la memoria ocupada por unEntero y arrayDeEnteros
respectivamente, quedaría ocupada sin sentido. Cuando
Constructores + Memoria heap Un objeto creado de la una porción de memoria queda ocupada por una variable
forma que se vio hasta ahora, es un objeto que vive dentro que ya no se utiliza, y no hay forma de acceder a ella, se
del scope(las llaves { }) en el que fue creado. Para que un denomina un 'memory leak'. En aplicaciones grandes, si
objeto pueda seguir viviendo cuando se saque de el sco- ocurren muchos memory leaks, el programa puede ter-
pe en el que se creó, se lo debe crear en memoria heap. minar ocupando bastante más memoria RAM de la que
Para esto, se utiliza el operador new, el cual asigna memo- debería, lo que no es para nada conveniente. Es por esto,
ria para almacenar al objeto creado, y además llama a su que el manejo de memoria heap debe usarse consciente-
constructor(por lo que se le pueden enviar parámetros). mente.
El operador new se utiliza de la siguiente manera:
Existen dos tipos de destructores pueden ser públicos o
int main() { Punto *unPunto = new Punto(); //esto llama privados, según si se declaran:
al constructor que se describe más arriba delete unPunto;
//no hay que olvidarse de liberar la memoria ocupada
por el objeto(ver la sección destructores, más abajo) • Si es público se llama desde cualquier parte del pro-
return 0; } grama para destruir el objeto.
la clase para llamar a esta función, sin embargo, sólo se ConcretaA : public Abstracta { public: int metodo() {
podrá acceder a los miembros estáticos de la clase da- //haz algo return foo () + 2; } }; class ConcretaB : public
do que estos no están asociados al objeto sino al tipo. Abstracta { public: int metodo() { //otra implementación
La sintaxis para llamar a esta función estática es myty- return baz () - 5; } };
pe::mystaticmember().
En el ejemplo, la clase ConcretaA es una implementación
de la clase Abstracta, y la clase ConcretaB es otra imple-
4.4 Plantillas
mentación. Debe notarse que el = 0 es la notación que
Las plantillas son el mecanismo de C++ para implantar emplea C++ para definir funciones virtuales puras.
el paradigma de la programación genérica. Permiten que
una clase o función trabaje con tipos de datos abstrac-
tos, especificándose más adelante cuales son los que se 4.6 Espacios de nombres
quieren usar. Por ejemplo, es posible construir un vector
genérico que pueda contener cualquier tipo de estructu- Una adición a las características de C son los espacios de
ra de datos. De esta forma se pueden declarar objetos de nombre (namespace en inglés), los cuales pueden descri-
la clase de este vector que contengan enteros, flotantes, birse como áreas virtuales bajo las cuales ciertos nombres
polígonos, figuras, fichas de personal, etc. de variable o tipos tienen validez. Esto permite evitar las
ocurrencias de conflictos entre nombres de funciones, va-
La declaración de una plantilla se realiza anteponiendo la riables o clases.
declaración template <typename A,....> a la declaración
de la estructura (clase, estructura o función) deseado. El ejemplo más conocido en C++ es el espacio de nom-
bres std::, el cual almacena todas las definiciones nue-
Por ejemplo: vas en C++ que difieren de C (algunas estructuras y fun-
template <typename T> T max(const T &x, const T &y) ciones), así como las funcionalidades propias de C++
{ return (x > y) ? x : y; //si x > y, retorna x, sino retorna y } (streams) y los componentes de la biblioteca STL.
Por ejemplo:
La función max() es un ejemplo de programación gené- # include <iostream> // Las funciones en esta cabecera
rica, y dados dos parámetros de un tipo T (que puede ser existen dentro del espacio de nombres std:: namespace
int, long, float, double, etc.) devolverá el mayor de ellos mi_paquete{ int mi_valor; }; int main() { int mi_valor =
(usando el operador >). Al ejecutar la función con pará- 3; mi_paquete::mi_valor = 4; std::cout << mi_valor <<
metros de un cierto tipo, el compilador intentará “calzar” '\n'; // imprime '3' std::cout << mi_paquete::mi_valor <<
la plantilla a ese tipo de datos, o bien generará un mensaje '\n'; // imprime '4' return 0; }
de error si fracasa en ese proceso.
En la herencia, las clases derivadas “heredan” los datos 4.7.2 Herencia múltiple
y las funciones miembro de las clases base, pudiendo las
clases derivadas redefinir estos comportamientos (poli- La herencia múltiple es el mecanismo que permite al pro-
morfismo) y añadir comportamientos nuevos propios de gramador hacer clases derivadas a partir, no de una sola
las clases derivadas. Para no romper el principio de en- clase base, sino de varias. Para entender esto mejor, pon-
capsulamiento (ocultar datos cuyo conocimiento no es ne- gamos un ejemplo: Cuando ves a quien te atiende en una
cesario para el uso de las clases), se proporciona un nuevo tienda, como persona que es, podrás suponer que puede
modo de visibilidad de los datos/funciones: “protected”. hablar, comer, andar, pero, por otro lado, como emplea-
Cualquier cosa que tenga visibilidad protected se com- do que es, también podrás suponer que tiene un jefe, que
portará como pública en la clase Base y en las que compo- puede cobrarte dinero por la compra, que puede devol-
nen la jerarquía de herencia, y como privada en las clases verte el cambio, etc. Si esto lo trasladamos a la progra-
que NO sean de la jerarquía de la herencia. mación sería herencia múltiple (clase empleado_tienda):
Antes de utilizar la herencia, nos tenemos que hacer una class Persona { ... Hablar(); Caminar(); ... }; class
pregunta, y si tiene sentido, podemos intentar usar esta je- Empleado { Persona jefe; int sueldo; Cobrar(); ... };
rarquía: Si la frase <claseB> ES-UN <claseA> tiene sen- class EmpleadoTienda: public Persona, Empleado { ...
tido, entonces estamos ante un posible caso de herencia AlmacenarStock(); ComprobarExistencias(); ... };
donde clase A será la clase base y clase B la derivada.
Ejemplo: clases Barco, Acorazado, Carguero, etc. Un Por tanto, es posible utilizar más de una clase para que
Acorazado ES-UN Barco, un Carguero ES-UN Barco, un otra herede sus características.
Trasatlántico ES-UN Barco, etc.
En este ejemplo tendríamos las cosas generales de un Bar-
4.8 Sobrecarga de operadores
co (en C++)
class Barco { protected: char* nombre; float peso; public: La sobrecarga de operadores es una forma de hacer
//Constructores y demás funciones básicas de barco }; polimorfismo. Es posible definir el comportamiento de un
operador del lenguaje para que trabaje con tipos de da-
tos definidos por el usuario. No todos los operadores de
y ahora las características de las clases derivadas, podrían
C++ son factibles de sobrecargar, y, entre aquellos que
(a la vez que heredan las de barco) añadir cosas propias
pueden ser sobrecargados, se deben cumplir condiciones
del subtipo de barco que vamos a crear, por ejemplo:
especiales. En particular, los operadores sizeof y :: no son
class Carguero: public Barco { // Esta es la manera de sobrecargables.
especificar que hereda de Barco private: float carga; //El
No es posible en C++ crear un operador nuevo.
resto de cosas }; class Acorazado: public Barco { private:
int numeroArmas; int Soldados; // El resto de cosas }; Los comportamientos de los operadores sobrecargados se
implementan de la misma manera que una función, salvo
que esta tendrá un nombre especial: Tipo de dato de de-
Por último, hay que mencionar que existen 3 clases de
volución operator<token del operador>(parámetros)
herencia que se diferencian en el modo de manejar la vi-
sibilidad de los componentes de la clase resultante: Los siguientes operadores pueden ser sobrecargados:
• Operadores Unarios
• Herencia publica (class Derivada: public Base ): Con
este tipo de herencia se respetan los comportamien- • Operador * (de indirección)
tos originales de las visibilidades de la clase Base en • Operador -> (de indirección)
la clase Derivada.
• Operador & (de dirección)
• Operador +
• Herencia privada (clase Derivada: private Base):
• Operador -
Con este tipo de herencia todo componente de la
clase Base, será privado en la clase Derivada (las • Operador ++
propiedades heredadas serán privadas aunque estas • Operador --
sean públicas en la clase Base)
• Operadores Binarios
Dado que estos operadores son definidos para un tipo de Es posible formatear la entrada/salida, indicando el nú-
datos definido por el usuario, éste es libre de asignarles mero de dígitos decimales a mostrar, si los textos se pasa-
cualquiera semántica que desee. Sin embargo, se consi- rán a minúsculas o mayúsculas, si los números recibidos
dera de primera importancia que las semánticas sean tan están en formato octal o hexadecimal, etc.
parecidas al comportamiento natural de los operadores
como para que el uso de los operadores sobrecargados
sea intuitivo. Por ejemplo, el uso del operador unario - 6.1 Fstreams
debiera cambiar el “signo” de un “valor”.
Tipo de flujo para el manejo de ficheros. La definición
Los operadores sobrecargados no dejan de ser funciones,
previa de ostreams/istreams es aplicable a este apartado.
por lo que pueden devolver un valor, si este valor es del
Existen tres clases (ficheros de lectura, de escritura o de
tipo de datos con el que trabaja el operador, permite el
lectura/escritura): ifstream,ofstream y fstream.
encadenamiento de sentencias. Por ejemplo, si tenemos
3 variables A, B y C de un tipo T y sobrecargamos el Como abrir un fichero: (nom-
operador = para que trabaje con el tipo de datos T, hay bre_variable_fichero).open(“nombre_fichero.dat/txt”,ios::in);
dos opciones: si el operador no devuelve nada una senten- para abrirlo en modo lectura. (nombrevariablefiche-
cia como “A=B=C;" (sin las comillas) daría error, pero si ro).open(“nombre_fichero.dat/txt”,ios::out); para abrirlo
se devuelve un tipo de datos T al implementar el opera- en modo escritura.
dor, permitiría concatenar cuantos elementos se quisie- Ejemplo: f.open(“datos.txt”,ios::in);
ran, permitiendo algo como “A=B=C=D=...;"
Como cerrar el fichero: nombre_variable_fichero.close();
Ejemplo: f.close();
5 Standard Template Library Leer un fichero:
(STL) 1-Si es fichero de texto plano:
#include <fstream> #include <string> #include <ios-
Los lenguajes de programación suelen tener una serie tream> using namespace std; int main() { ifstream
de bibliotecas de funciones integradas para la manipu- entrada; entrada.open(“textoPlano.txt”); string unString;
lación de datos a nivel más básico. En C++, además de while(entrada >> unString) cout << “Lei: " << unString
poder usar las bibliotecas de C, se puede usar la nativa << endl; return 0; }
8 6 BIBLIOTECA DE ENTRADA Y SALIDA
2-Si es un fichero binario(.dat); nom- Para añadir elementos al final del vector, se utiliza el mé-
bre_variable_fichero.read((char*)&nombre_variable, todo push_back(const T&). Por otro lado, para eliminar
sizeof(tipo_variable)); Ejemplo: f.read((char*)&e, un elemento del final del vector, se debe usar el método
sizeof(int)); pop_back().
Escribir un fichero: #include <vector> //libreria que contiene a la clase
1-Si es fichero de texto(.txt): nombrevariable<<"texto"; vector #include <iostream> using namespace std; int
main() { vector<int> intVector; //crea un vector de en-
donde “texto” puede ser también una variable de
cualquier tipo primitivo, o un string. Ejemplo: teros(sin elementos) intVector.push_back(25); //agrega
f<<HOLA; 2-Si es un fichero binario(.dat); nom- el entero 25 al vector cout << “El primer elemento
bre_variable_fichero.write((char*)&nombre_variable, es: " << intVector.front() << " y mi vector tiene " <<
sizeof(tipo_variable)); Ejemplo: f.write((char*)&e, intVector.size() << " elementos.” << endl; //imprime
sizeof(int)); el primer elemento(retornado por el método front()
intVector.push_back(32); //agrego el entero 32 al vector
Pueden abrirse pasando al constructor los parámetros re- cout << “El primer elemento es: " << intVector[0] <<
lativos a la ubicación del fichero y el modo de apertura: endl; //imprime 25 intVector.pop_back(); //elimina el
ultimo elemento del vector(osea 32) cout << “Ahora
tengo: " << intVector.size() << " elementos.” << endl;
6.2 Sstreams //imprimirá 1 return 0; }
Se destacan dos clases, ostringstream e istringstream.
Todo lo anteriormente dicho es aplicable a estas clases.
• Colas dobles: son parecidas a los vectores, pero tie-
Tratan a una cadena como si de un flujo de datos se tra-
nen mejor eficiencia para agregar o eliminar ele-
tase. ostringstream permite elaborar una cadena de texto
mentos en las “puntas”.deque<tipo_de_dato> nom-
insertando datos cual flujo, e istringstream puede extraer
bre_de_la_cola;
la información contenida en una cadena (pasada como
parámetro en su constructor) con el operador >>. Ejem-
Además de los métodos push_back(const T&) y
plos:
pop_back(), se agregan los métodos push_front(const
ostringstream s; s << nombre << ",” << edad << ",” T&) y pop_front(), que realizan lo mismo que los ya
<< estatura << ",” << punto(5,6) << endl; cout << explicados, pero en el comienzo de la cola.
s.str(); istringstream s(cadena); s >> nombre >> edad >>
#include <deque> //libreria de deques using na-
estatura >> p;
mespace std; int main() { deque<int> intDeque;
intDeque.push_front(25); intDeque.push_back(12);
while(intDeque.size()) intDeque.pop_back(); //borra
6.3 Contenedores todos los elementos return 0; }
• Vectores: Se definen por vector<tipo_de_dato> • Contenedores asociativos: map y multimap, que per-
nombre_del_vector; Son arrays (o listas ordenadas) miten asociar una “clave” con un “valor”. map no
que se redimensionan automáticamente al agregar permite valores repetidos, mientras que multimap
nuevos elementos, por lo que se le pueden agre- si.
gar “teóricamente”, infinitos elementos. Los vecto-
res nos permiten acceder a cualquier elemento que map<tipo_de_llave, tipo_de_dato> nombre_del_map;
contenga, mediante el operador[]. Debe tenerse en multimap<tipo_de_llave, tipo_de_dato> nom-
cuenta que si se intenta acceder a una posición que bre_del_multimap;
excede los límites del vector, este no hará ningún #include <map> //libreria que contiene a map y mul-
chequeo, por lo que se debe ser cuidadoso al utili- timap #include <string> //libreria de strings #include
zar este operador. Para asegurar un acceso seguro al <iostream> //libreria de entrada/salida using namespace
vector, se puede utilizar el método at(int), que lanza std; int main() { map<int, string> intAString; intAS-
una excepción de tipo std::out_of_range en caso de tring[1] = “uno"; intAString[10] = “diez"; cout << “En
que esto ocurra. intAString[1]: " << intAString[1] << endl; cout << “En
9
combinación de las anteriores, entonces las dos con- 11.2 Bajo MacOS
diciones establecidas previamente deben aplicar pa-
ra cada tipo de dato constituyente. • Xcode
• Geany
9 Compiladores • Zinjai
[2] http://herbsutter.com/2011/08/12/
10 Ejemplo: Cmd con colores we-have-an-international-standard-c0x-is-unanimously-approved/
• C/C++ Reference
• C/C++ Programming
14.2 Images
• Archivo:C_plus_plus.svg Fuente: http://upload.wikimedia.org/wikipedia/commons/5/5b/C_plus_plus.svg Licencia: Public domain Cola-
boradores: Trabajo propio Artista original: JTojnar
• Archivo:Commons-logo.svg Fuente: http://upload.wikimedia.org/wikipedia/commons/4/4a/Commons-logo.svg Licencia: Public domain
Colaboradores: This version created by Pumbaa, using a proper partial circle and SVG geometry features. (Former versions used to be slightly
warped.) Artista original: SVG version was created by User:Grunt and cleaned up by 3247, based on the earlier PNG version, created by
Reidab.