CONCEPTO DE C++
C++ es un lenguaje de
programación diseñado
en 1979 por Bjarne Stroustrup.
La intención de su creación fue extender al lenguaje de programación C mecanismos que permiten la manipulación
de objetos. En ese sentido, desde el punto de vista de
los lenguajes
orientados a objetos, el C++ es un lenguaje híbrido.
Posteriormente se
añadieron facilidades de programación genérica, que se sumaron a los paradigmas de programación
estructurada y programación
orientada a objetos. Por esto se suele decir que el C++ es un lenguaje
de programación multiparadigma.
Actualmente existe un
estándar, denominado ISO C++, al que se han adherido la mayoría de los
fabricantes de compiladores más modernos. Existen también algunos intérpretes,
tales como ROOT.
Una particularidad del
C++ es la posibilidad de redefinir los operadores, y de poder crear nuevos tipos que se comporten como tipos fundamentales.
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++"
significa "incremento de C" y se refiere a que C++ es una extensión
de C
Ejemplo:
/* Esta cabecera permite usar los objetos que
encapsulan los descriptores stdout
y stdin: cout(<<) y cin(>>)*/
#include <iostream>
using namespace std;
int main()
{
cout << "Hola mundo" << endl;
return 0;
}
Al usar la directiva
#include se le dice al
compilador que busque e interprete todos los elementos definidos en el archivo
que acompaña la directiva (en este caso, iostream). Para
evitar sobrescribir los elementos ya definidos al ponerles igual nombre, se
crearon los espacios de nombres o namespace del
singular en inglés. En este caso hay un espacio de nombres llamado std, que es
donde se incluyen las definiciones de todas las funciones y clases que
conforman la biblioteca estándar
de C++. Al incluir la sentencia using namespace std le
estamos diciendo al compilador que usaremos el espacio de nombres std por
lo que no tendremos que incluirlo cuando usemos elementos de este espacio de
nombres, como pueden ser los objetos cout y cin, que
representan el flujo de salida estándar (típicamente la pantalla o una ventana
de texto) y el flujo de entrada estándar (típicamente el teclado).
La definición de funciones es igual que en C, salvo por la característica
de que si
main no va a recoger argumentos, no tenemos
por qué ponérselos, a diferencia de C, donde había que ponerlos explícitamente,
aunque no se fueran a usar. Queda solo comentar que el símbolo << se
conoce como operador de inserción, y grosso modo está enviando
a coutlo que
queremos mostrar por pantalla para que lo pinte, en este caso la cadena "Hola mundo". El
mismo operador <<se puede usar varias veces en la
misma sentencia, de forma que gracias a esta característica podremos concatenar
el objeto endl al final, cuyo resultado será imprimir
un retorno de línea
Tipos de datos
·
Caracteres: char (también es un entero), wchar_t
·
Enteros: short, int, long, long long
·
Números en coma flotante: float, double, long double
·
Booleanos: bool
·
Vacío: void
El modificador
unsigned se puede
aplicar a enteros para obtener números sin signo (por omisión los enteros
contienen signo), con lo que se consigue un rango mayor de números naturales.
Tamaños asociados
Según la máquina y el compilador que
se utilice los tipos primitivos pueden ocupar un determinado tamaño en memoria.
La siguiente lista ilustra el número de bits que ocupan los distintos tipos
primitivos en la arquitectura x86.
|
Tamaños de tipos primitivos bajo
i386 (GCC)
|
|
|
Tipo
|
Número de bits
|
|
char
|
8
|
|
short
|
16
|
|
int
|
32
|
|
float
|
32
|
|
double
|
64
|
Otras arquitecturas pueden requerir distintos
tamaños de tipos de datos primitivos. C++ no dice nada acerca de cuál es el
número de bits en un byte, ni del tamaño de estos tipos; más bien, ofrece
solamente las siguientes "garantías de tipos":
·
De acuerdo al estándar C99, un tipo char debe ocupar
exactamente un bytecompuesto de un mínimo de 8 bits independientemente
de la arquitectura de la máquina.
·
El tamaño reconocido de char es de 1. Es
decir, sizeof(char) siempre devuelve 1.
·
Un tipo short tiene al menos el mismo tamaño que un tipo char.
·
Un tipo long tiene al menos el doble tamaño en bytes que un
tipo short.
·
Un tipo int tiene un tamaño entre el de short y el de long, ambos inclusive,
preferentemente el tamaño de un apuntador de memoria de la máquina. Su valor
máximo es 2147488281, usando 32 bits.
·
Un tipo unsigned tiene el mismo tamaño que su versión signed.
Wchar-_t
Para la versión del estándar que se publicó en 1998, se decidió
añadir el tipo de dato
wchar_t, que permite el uso de
caracteres UNICODE, a diferencia del
tradicional char, que contempla simplemente al código de
caracteres ASCII extendido. A su vez, se ha definido para la mayoría de las
funciones y clases, tanto de C como de C++, una versión para trabajar con wchar_t, donde
usualmente se prefija el carácter w al nombre de la función
(en ocasiones el carácter es un infijo). Por ejemplo:
·
strcpy - wstrcpy
·
std::string - std::wstring
·
std::cout - std::wcout
Cabe resaltar que en C se
define wchar_t como:
typedef unsigned short wchar_t;
Mientras que en C++ es en sí mismo un
tipo de dato.
La palabra reservada “void”
La palabra reservada
void define en C++ el
concepto de no existencia o no atribución de un tipo en una variable o
declaración. Es decir, una función declarada como void no
devolverá ningún valor. Esta palabra reservada también puede usarse para
indicar que una función no recibe parámetros, como en la siguiente declaración:int funcion (void);
Aunque la tendencia actual es la de no colocar la palabra
"void".
Además se utiliza para determinar que una función no retorna un
valor, como en:
void funcion (int parametro);
Cabe destacar que
void no
es un tipo. Una función como la declarada anteriormente no puede retornar
un valor por medio de return: la
palabra clave va sola. No es posible una declaración del tipo:void t; //Está mal
En este sentido,
void se comporta de forma
ligeramente diferente a como lo hace en C, especialmente en cuanto a su
significado en declaraciones y prototipos de funciones.
Sin embargo, la forma especial void * indica
que el tipo de datos es un puntero. Por ejemplo:
void *memoria;
Indica que memoria es un puntero a alguna parte,
donde se guarda información de algún tipo. El programador es
responsable de definir estos "algún", eliminando toda ambigüedad. Una
ventaja de la declaración "void *" es que puede representar a
la vez varios tipos de datos, dependiendo de la operación de cast escogida.
La memoria que hemos apuntado en alguna parte, en el ejemplo anterior, bien
podría almacenar un entero, un flotante, una cadena de texto o un programa, o
combinaciones de estos. Es responsabilidad del programador recordar qué tipo de
datos hay y garantizar el acceso adecuado.
La palabra “NULL”
Además de los valores que pueden tomar los tipos anteriormente
mencionados, existe un valor llamado NULL, sea el caso numérico para los
enteros, carácter para el tipo char, cadena de texto para el tipo string, etc.
El valor NULL, expresa, por lo regular, la representación de una Macro,
asignada al valor "0".
Tenemos entonces que:
void* puntero = NULL;
int entero = NULL;
bool boleana = NULL;
char caracter = NULL;
El valor de las variables anteriores nos daría 0. A diferencia
de la variable "caracter", que nos daría el equivalente a NULL, '\0',
para caracteres.
Principios
Todo programa en C++ debe tener la función principal
main() (a
no ser que se especifique en tiempo de compilación otro punto de entrada, que
en realidad es la función que tiene el main())int main()
{}
La función
principal del código fuente main debe tener
uno de los siguientes prototipos:
int main()
int
main(int argc, char** argv)
Aunque no es estándar algunas implementaciones
permiten
int
main(int argc, char** argv, char** env)
La primera es la forma por omisión de un programa que no recibe
parámetros ni argumentos. La segunda forma tiene dos parámetros: argc,
un número que describe el número de argumentos del programa (incluyendo el
nombre del programa mismo), y argv, un puntero a un array de
punteros, de argc elementos, donde el elemento argv[i] representa
el i-ésimo argumento entregado al programa. En el tercer caso se
añade la posibilidad de poder acceder a las variables de entorno de ejecución
de la misma forma que se accede a los argumentos del programa, pero reflejados
sobre la variable env.
El tipo de retorno de main es un valor entero int. Al
finalizar la función
main, debe incluirse el valor
de retorno (por ejemplo, return 0;, aunque el estándar prevé solamente dos
posibles valores de retorno: EXIT_SUCCESS y EXIT_FAILURE, definidas en el
archivo cstdlib), o
salir por medio de la función exit. Alternativamente puede dejarse en blanco, en cuyo caso el
compilador es responsable de agregar la salida adecuada.
El concepto de clase
Los objetos en C++ son abstraídos
mediante una clase. Según el paradigma de la programación orientada a objetos
un objeto consta de:
1. Identidad, que lo
diferencia de otros objetos (Nombre que llevará la clase a la que pertenece
dicho objeto).
2. Métodos o funciones
miembro.
3. Atributos o
variables miembro.
Un ejemplo de clase que podemos tomar
es la clase perro. Cada perro comparte unas características (atributos). Su
número de patas, el color de su pelaje o su tamaño son algunos de sus
atributos. Las funciones que lo hagan ladrar, cambiar su comportamiento... esas
son las funciones de la clase.
Este es otro ejemplo de una clase:
class Punto
{
//por omisión, los miembros son 'private' para que solo se puedan modificar desde la propia clase.
private:
// Variable miembro privada
int id;
protected:
// Variables miembro protegidas
int x;
int y;
public:
// Constructor
Punto();
// Destructor
~Punto();
// Funciones miembro o métodos
int ObtenerX();
int ObtenerY();
};
Constructores
Son unos métodos especiales que se ejecutan automáticamente al
crear un objeto de la clase. En su declaración no se especifica el tipo de dato
que devuelven, y poseen el mismo nombre que la clase a la que pertenecen. Al
igual que otros métodos, puede haber varios constructores sobrecargados, aunque
no pueden existir constructores virtuales.
Como característica especial a la hora de implementar un
constructor, justo después de la declaración de los parámetros, se encuentra lo
que se llama "lista de inicializadores". Su objetivo es llamar a los
constructores de los atributos que conforman el objeto a construir.
Cabe destacar que no es necesario declarar un constructor al
igual que un destructor, pues el compilador lo puede hacer, aunque no es la
mejor forma de programar.
Tomando el ejemplo de la Clase Punto, si deseamos que cada vez
que se cree un objeto de esta clase las coordenadas del punto sean igual a cero
podemos agregar un constructor como se muestra a continuación:
class Punto
{
public:
float x; // Coordenadas del punto
float y;
// Constructor
Punto() : x(0), y(0){ // Inicializamos las variables "x" e "y"
}
};
// Main para demostrar el funcionamiento de la clase
# include <iostream> // Esto nos permite utilizar "cout"
using namespace std;
int main () {
Punto MiPunto; // creamos un elemento de la clase Punto llamado MiPunto
cout << "Coordenada X: " << MiPunto.x << endl; // mostramos el valor acumulado en la variable x
cout << "Coordenada Y: " << MiPunto.y << endl; // mostramos el valor acumulado en la variable y
getchar(); // le indicamos al programa que espere al buffer de entrada (detenerse)
return 0;
}
Si compilamos y ejecutamos el
anterior programa, obtenemos una salida que debe ser similar a la siguiente:
Coordenada X: 0 Coordenada Y: 0
Existen varios tipos de constructores
en C++:
1. Constructor
predeterminado. Es el constructor que no recibe ningún parámetro en la función. Si no
se definiera ningún constructor, el sistema proporcionaría uno predeterminado.
Es necesario para la construcción de estructuras y contenedores de la STL.
2. Constructor de
copia. Es un constructor que recibe un objeto de la misma clase, y realiza
una copia de los atributos del mismo. Al igual que el predeterminado, si no se
define, el sistema proporciona uno.
3. Constructor de
conversión. Este constructor, recibe como único parámetro, un objeto o variable de
otro tipo distinto al suyo propio. Es decir, convierte un objeto de un tipo
determinado a otro objeto del tipo que estamos generando.
Constructores + Memoria heap Un objeto creado de la forma que se vio hasta ahora, es
un objeto que vive dentro del scope(las llaves { }) en el que fue creado. Para
que un objeto pueda seguir viviendo cuando se saque del scope en el que se
creó, se lo debe crear en memoria heap. Para esto, se utiliza el operador new,
el cual asigna memoria para almacenar al objeto creado, y además llama a su
constructor(por lo que se le pueden enviar parámetros). El operador new se
utiliza de la siguiente manera:
int main() {
Punto *unPunto = new Punto(); //esto llama 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)
return 0;
}
Además, con el operador new[] se pueden crear arrays
(colecciones o listas ordenadas) de tamaño dinámico:
Punto *asignar(int cuantos) {
return new Punto[cuantos]; //asigna un array de 'cuantos' puntos(se llama el constructor que se muestra más arriba), y se retorna.
}
.
Luis Orduz calificación 45
ResponderEliminar