|
2.1
Comentarios
C++
soporta dos tipos de comentarios:
1. Viejo estilo
C: Entre /* y */.
2. Nuevo estilo C++: Comienzan con //.
Su efecto termina cuando se alcanza el final de la línea actual.
2.2
Identificadores
Son
los nombres elegidos para las variables, constantes, funciones, clases y
similares. El primer carácter debe ser una letra o un subrayado. El resto del
nombre puede contener dígitos. Los identificadores que comienzan con dos
subrayados están reservados para uso interno del compilador C++.
2.3
Constantes
C++
permite utilizar varios tipos de constantes:
1. Constantes enteras
44 0 -345
2. Constantes enteras muy grandes. Se
identifican situando una L al final de la constante entera
33L -105L
3. Constantes octales o hexadecimales.
Un 0 a la izquierda indica una constante octal y un 0x o bien 0X indican una
constante hexadecimal
0
02 077 0123 equivalen a 0 2 63 83 en octal
0x0 0x2 0x3F 0x53 equivalen a 0 2 63 83 en hexadecimal
4. Constantes reales (coma flotante)
0.0 3.1416 -99.2
C++ permite especificar constante de coma flotante de simple precisión (sufijo
f o F) y doble precisión larga (sufijo l o L).
32.0f 3.1416L
5. Constantes carácter
'z' '5'
6. Constantes cadena "hola"
"hoy es lunes"
2.4
Tipos de
datos
C++,
igual que C, contiene tipos fundamentales
y tipos derivados o estructurados.
Los fundamentales son: int, char, long int, float, double, long double.
- Tipo vacío. El tipo vacío (void)
se utiliza principalmente para especificar:
* Funciones que no devuelven valores.
* Punteros void, que referencian a objetos cuyo tipo es desconocido.
-
Tipos enumerados. Un tipo enumerado o enumeración está construido
por una serie de constantes simbólicas enteras. Los tipos enumerados se tratan
de modo ligeramente diferente en C++ que en ANSI C. El nombre de la etiqueta enum
se considera como un nombre de tipo igual que las etiquetas de struct y
union. Por tanto se puede declarar una variable de enumeración, estructura o
union sin utilizar las palabras enum, strcut o union.
C define el tipo de enum de tipo int. En C++, sin embargo, cada tipo enumerado
es su propio tipo independiente. Esto significa que C++ no permite que un valor
int se convierta automáticamente a un valor enum. Sin embargo, un valor
enumerado se puede utilizar en lugar de un int.
Ej. enum lugar{primero,segundo,tercero};
lugar pepe=primero; //correcto
int vencedor=pepe; //correcto
lugar juan=1;
//incorrecto
La última sentencia de asignación es aceptable en C pero no en C++, ya que 1
no es un valor definido en lugar.
-
Tipos referencia. Las referencias son como alias. Son alternativas al nombre de un objeto. Se define un tipo
referencia haciéndole preceder por el operador de dirección &.
Un objeto referencia, igual que una constante debe ser inicializado.
int a=50;
int &refa=a; //correcto
int &ref2a; //incorrecto:
no inicializado
Todas las operaciones efectuadas sobre la referencia se realizan sobre el propio
objeto:
refa+=5; equivale a sumar 5 a a, que vale ahora 55
int *p=&refa; inicializa p con la dirección de a
2.5
Operadores
especiales de C++
| :: |
Resolución
de ámbito (o alcance) |
| .* |
Indirección
(eliminación de referencia directa) un puntero a un miembro de una clase |
| ->* |
Indirección
(eliminación de referencia directa) un puntero a un miembro de una clase |
| new |
Asigna
(inicializa) almacenamiento dinámico |
| delete |
Libera
almacenamiento asignado por new |
2.6
Declaraciones
y definiciones
Los
términos declaración y definición tienen un significado distinto aunque con
frecuencia se intercambian.
Las declaraciones se utilizan para introducir un nombre nombre al
compilador, pero no se asigna memoria. Las definiciones
asignan memoria.
En C++ cuando se declara una estructura se proporciona su nombre al compilador
pero no se asigna memoria. Cuando se crea una instancia de la estructura es cuando se asigna memoria.
En C todas las declaraciones dentro de un programa o función deben hacerse al
principio del programa o función; en otras palabras las declaraciones dentro de
un ámbito dado deben ocurrir al principio de ese ámbito.. Todas las
declaraciones globales deben aparecer antes de cualquier función y cualquier
declaración local debe hacerse antes de cualquier sentencia ejecutable.
C++, por el contrario, permite mezclar datos con funciones y código ejecutable:
trata una declaración como un tipo de sentencia y permite situarla en cualquier
parte como tal. Esta característica de C++ es muy cómoda ya que permite
declarar una variable cuando se necesite e inicializarla inmediatamente.
El ámbito de una variable es el bloque actual y todos los bloques subordinados
a él. Su ámbito comienza donde aparece la declaración. Las sentencias C++ que
aparecen antes de la declaración no pueden referirse a la variable incluso
aunque aparezcan en el mismo bloque que la declaración de la variable.
2.7
Moldes
(cast)
C++
soporta dos formas diferentes de conversiones forzosas de tipo explícitas:
| int
f=0; |
|
| long
l= (long) f; |
molde
tradicional, tipo C |
| long
n = long (f); |
molde
nuevo, tipo C++ |
La
sintaxis nombre_tipo (expresión)
se conoce como notación funcional y es preferible por su legibilidad.
2.8
El
especificador constante (const)
Una
constante es una entidad cuyo valor no se puede modificar, y en C++, la palabra
reservada const se utiliza para
declarar una constante.
const
int longitud = 20;
char array[longitud]; // válido
en C++ pero no en C
Una
vez que una constante se declara no se puede modificar dentro del programa.
En C++ una constante debe ser inicializada cuando se declara, mientras que en
ANSI C, una constante no inicializada se pone por defecto a 0.
La diferencia más importante entre las constantes en C++ y C es el modo como se
declaran fuera de las funciones. En ANSI C se tratan como constantes globales y
se pueden ver por cualquier archivo que es parte del programa. En C++, las
constantes que se declaran fuera de una función tienen ámbito de archivo por
defecto y no se pueden ver fuera del archivo en que están declaradas. Si se
desea que una constante se vea en más de un archivo, se debe declarar como
extern.
En C++ las constantes se pueden utilizar para sustituir a #define.
|
En
C |
En
C++ |
| #define
PI 3.141592 |
const
PI = 3.141592 |
| #define
long 128 |
const
long = 128 |
2.9
Punteros y
direcciones de constantes simbólicas
No
se puede asignar la dirección de una constante no simbólica a un puntero no
constante, pero sí se puede desreferenciar el puntero y cambiar el valor de la
constante.
const
int x=6;
int *ip;
ip = &x; //error
*ip=7;
Punteros
a un tipo de dato constante
Se
puede declarar un puntero a un tipo de dato constante pero no se puede
desreferenciar.
const
int x=6;
const int *ip;
//puntero a una constante entera
int
z;
ip=&x;
ip=&z;
*ip=10;
//error: no se puede desreferenciar este tipo de puntero y modificar z
z=7;
//válido: z no es una constante y se puede cambiar
El
puntero a un tipo constante es muy útil cuando se desea pasar una variable
puntero como un argumento a una función pero no se desea que la función cambie
el valor de la variable a la que está apuntada.
struct ejemplo
{
int x;
int y;
};
void funcion(const ejemplo *);
void main()
{
ejemplo e={4,5};
funcion(&e); //convertirá
un puntero no constante a un puntero const
}
void funcion(const ejemplo *pe)
{ ejemplo i;
i.x=pe->x;
i.y=pe->y;
pe->x=10; } // error: no se puede desreferenciar pe
Punteros
constantes
Se
puede definir una constante puntero en C++. Las constantes puntero se deben
inicializar en el momento en que se declaran. Se leen de derecha a izquierda.
void
main()
{
int x=1,y;
int *const xp=
&x; // xp es un puntero constante
a un int
xp=&y;
// error: el puntero es una constante y no se puede asignar un nuevo
valor a punteros constantes
*xp=4;
}
2.10
El
especificador
de tipo volatile
La
palabra reservada volatile se utiliza
sintácticamente igual que const, aunque en cierto sentido tiene sentido
opuesto.
La
declaración de una variable volátil indica al compilador que el valor de esa
variable puede cambiar en cualquier momento por sucesos externos al control del
programa. En principio, es posible que las variables volátiles se puedan
modificar no sólo por el programador sino también por hardware o software del
sistema (rutina de interrupción).
volatile int puerto;
2.11
Sizeof (char)
En
C, todas las constantes char se almacenan como enteros. Esto significa que en C
un carácter ocupa lo mismo que un entero. En C++ un char se trata como un byte,
y no como el tamaño de un int. Por ejemplo en una máquina con una palabra de 4
bytes sizeof('a') se evalúa a 1 en C++ y a 4 en C.
2.12
Punteros a
void
En
C, una variable puntero siempre apunta a un tipo de dato específico, de modo
que el tipo de dato es importante para aritmética de punteros. Si se intenta
inicializar una variable puntero con el tipo de dato incorrecto, el compilador
genera un mensaje de error. En C se pueden moldear los datos al tipo de dato
correcto:
void
main()
{
int a=1,*p;
double x=2.4;
p=&a;
//válido: puntero y variable son del mismo tipo
p=&x;
//error
p=(int *)&x; //válido
}
En
C++ se puede crear un puntero genérico
que puede recibir la dirección de cualquier tipo de dato.
void
main()
{ void *p;
int a=1;
double x=2.4;
p=&a;
p=&x; }
No se puede desrefernciar un puntero
void.
void
main()
{ void *p;
double x=2.5;
p=&x;
*p=3.6;
// error: se desreferencia a un puntero void
}
2.11
Salidas y
entradas
Las
operaciones de salida y entrada se realizan en C++, al igual que en C, mediante
flujos (streams) o secuencias de datos. Los flujos estandar son cout (flujo de
salida) y cin (flujo de entrada). La salida fluye normalmente a la pantalla y la
entrada representa los datos que proceden de teclado. Ambos se pueden
redireccionar.
1.
Salida
El
flujo de salida se representa por el identificador cout,
que es en realidad un objeto. El operador <<
se denomina operador de inserción y
dirige el contenido de la variable situada a su derecha al objeto situado a su
izquierda. El equivalente en C de cout es printf.
El
archivo de cabecera iostream.h
contiene las facilidades standard de entrada y salida de C++.
En C++, los dispositivos de salida estandar no requieren la cadena de formato.
Se
pueden utilizar también diferente tipos de datos, enviando cada uno de ellos a
la vez al flujo de salida. El flujo cout discierne el formato del tipo de dato,
ya que el compilador C++ lo descifra en el momento de la compilación.
El
operador de inserción se puede utilizar repetidamente junto con cout.
include
<iostream.h>
void main()
{
int a=4;
float b=3.4;
char
*texto="hola\n";
cout<< "entero
" << a << " real " << b << " mensaje
" << texto;
}
Salida
con formato
C++
asocia un conjunto de manipuladores con el flujo de salida, que modifican el
formato por defecto de argumentos enteros. Por ejemplo, valores simbólicos de
manipuladores son dec, oct
y hex que visualizan representaciones
decimales, octales y hexadecimales de variable
2.
Entrada
C++
permite la entrada de datos a través del flujo de entrada cin.
El objeto cin es un objeto predefinido que corresponde al flujo de entrada estandar. Este flujo representa los datos que proceden del teclado. El operador >>
se denomina de extracción o de
lectura de. Toma el valor del objeto flujo de su izquierda y lo situa en la
variable situada a su derecha.
2.12
El
operador de
resolución de ámbito ::
C
es un lenguaje estructurado por bloques. C++ hereda la misma noción de bloque y
ámbito. En ambos lenguajes, el mismo identificador se puede usar para
referenciar a objetos diferentes. Un uso en un bloque interno oculta el uso
externo del mismo nombre. C++ introduce el operador de resolución de ámbito o
de alcance.
El
operador :: se utiliza para acceder a un elemento oculto en el ámbito
actual. Su sintaxis es
:: variable
Ejemplo:
#include <iostream.h>
int
a;
void main()
{
float a;
a=1.5;
::a=2;
cout << "a local " << a <<
"\n";
cout << "a global " << ::a <<
"\n";
}
Este programa visualiza:
a local 1.5
a global 2
Este
operador se utilizará también en la gestión de clases.
2.13
Estructuras
y uniones
Los
tipos definidos por el usuario se definen como estructuras, uniones,
enumeraciones o clases. Las estructuras y
uniones son tipos de clase (clase, es el tipo de dato fundamental en la
programación orientada a objetos).
El
tipo struct permite agregar componentes de diferentes tipos y con un solo
nombre. Las estructuras en C++ se declaran como en C:
struct
datos
{
int num;
char
nombre[20];
};
El
nuevo tipo de dato definido puede tener instancias que se declaran:
datos persona;
//declaración C++
struct datos persona;
// declaración C
En
C++ debe evitarse el uso de typedef.
El
mismo convenio aplicado a las estructuras, se aplica a las uniones.
Un
tipo especial de unión se ha incorporado a C++ :unión anónima. Una unión anónima
declara simplemente un conjunto de elementos que comparten la misma dirección
de memoria; no tiene nombre identificador y se puede acceder directamente a los
elementos por su nombre. Un ejemplo:
union
{
int
i;
float f;
};
Tanto
i como f comparten la misma posición de memoria. A los miembros de esta unión
se puede acceder directamente en el ámbito en que está declarada. Por tanto,
en el ejemplo, la sentencia i=3 sería aceptable.
Las
uniones anónimas son interesantes en el caso en que se defina una unión en el
interior de una estructura:
struct
registro
{
union
{
int num;
float salario;
};
char *telefono;
};
registro empleado;
Para
acceder al nombre de un campo dentro de esta estructura:
empleado.sueldo;
2.14
Asignación
dinámica de memoria: new y delete
En
C la asignación dinámica de memoria se manipula con las funciones
malloc() y free(). En C++ se
define un método de hacer asignación dinámica utilizando los operadores new
y delete.
En
C:
void main()
{
int *z;
z= (int*) malloc(sizeof(int));
*z=342;
printf("%d\n",*z);
free(z);
}
En
C++:
void main()
{
int *z=new int;
*z=342;
cout << z;
delete z;
}
El
operador new está disponible directamente en C++, de modo que no se necesita
utilizar ningún archivo de cabecera; new se puede utilizar con dos formatos:
new tipo
// asigna un único elemento
new tipo[num_eltos]
// signa un array
Si
la cantidad de memoria solicitada no está disponible, el operador new
proporciona el valor 0.
El
operador delete libera la memoria signada con new.
delete variable
delete [n] variable
new
es superior a malloc por tres razones:
1. new conoce cuánta memoria se asigna a cada tipo de variable.
2. malloc() debe indicar cuánta memoria asignar.
3. new hace que se llame a un constructor para el objeto asignado y
malloc no puede.
delete
produce una llamada al destructor en este orden:
1. Se llama al destructor
2. Se libera memoria
delete
es más seguro que free() ya que protege de intentar liberar memoria apuntada
por un puntero nulo.
|