General Apendice1
General Apendice1
General Apendice1
qxd
26/11/99 13:51
Pgina 527
APNDICE A
C FRENTE A C++
CONTENIDO
A.1.
A.2.
A.3.
A.4.
A.5.
A.6.
A.7.
A.8.
A.9.
A.10.
A.11.
Limitaciones de C.
Mejora de caractersticas de C en C++.
El primer programa C++.
Nuevas palabras reservadas de C++.
Comentarios.
Declaraciones de variables.
El especificador de tipos const.
Especificador de tipo void.
Los tipos char.
Cadenas.
Conversin obligatoria de tipos (Casting).
A.1.
LIMITACIONES DE C
1. No se pueden definir nuevos tipos. La facilidad typedef es esencialmente un mecanismo para especificar un sinnimo de un tipo
existente.
2. Las declaraciones de funciones no ayudan a la verificacin de tipos
en las llamadas a funciones. Las versiones K&R de C no especificaban nada sobre tipos de parmetros. En ANSI C se ha introducido
la declaracin de tipos de los parmetros, pero de modo opcional.
C++ exige de modo obligatorio los prototipos.
3. Cuando las funciones se compilan separadamente, no se realiza ninguna verificacin para asegurar que los tipos de argumentos corresponden a los tipos de parmetros. Si una funcin se compila separadamente, los compiladores C no verifican que esta funcin es
llamada consistentemente con respecto a su definicin.
4. No existen tipos de coma flotante de simple precisin. Todas las
variables de tipo float se convierten a double en expresiones o
cuando se pasan como argumentos. C++ soporta float como un
tipo distinto.
A.2.
C++ incorpora nuevas caractersticas no encontradas en ANSI C. Las mejoras se pueden agrupar en tres categoras:
aok.qxd
26/11/99 13:51
528
Pgina 528
Caractersticas
Propsito
Sobrecarga de operadores
Caractersticas
Propsito
Prototipos de funciones
Extensiones
de tipos
Clases derivadas
Funciones virtuales
Funciones amigas
Constructores
Destructores
Extensin
Propsito
Clases
Permite a las funciones y datos agruparse juntos, se utilizan para crear objetos.
Permite restringir el acceso a los datos y funciones de
una clase.
Clases que heredan propiedades de las clases base existentes y permite la reutilizacin y extensin de clases.
Permite acceso selectivo a miembros de acceso restringido de una clase.
Mecanismo que facilita el polimorfismo y que determina la funcin a llamar en tiempo de ejecucin, no en
tiempo de compilacin.
Crean las funciones definidas por el usuario para la inicializacin de objetos.
Se llaman automticamente para limpiar memoria cuando los objetos se tienen que borrar o liberar.
Control de acceso
Clases derivadas
Funciones amigas
Funciones virtuales
Constructores
Potencian C
Destructores
FIGURA A.1. Caractersticas de C++ frente a C.
aok.qxd
26/11/99 13:51
Pgina 529
C FRENTE A C++
529
A.3.1.
Hola programadores de C.
Bienvenidos al mundo de C++
se escribe as:
//archivo hola.cpp
#include <iostream.h>
int main ()
{
cout << Hola programadores de C. >> endl;
cout << Bienvenidos al mundo de C++ >> endl;
}
Los programadores de C reconocen la sentencia #include y la definicin de la funcin main (), pero no estn familiarizados con el archivo de
cabecera iostream.h.
Las facilidades de entrada y salida que se utilizan en programas C tambin se pueden utilizar en programas C++. Sin embargo, para mostrar las
nuevas propiedades de C++, el programa anterior utiliza las facilidades de
entrada/salida por flujos:
cout << Hola programadores de C. >> endl;
cout (como stdout) es el flujo de salida estndar. El operador << es
el flujo de salida. << escribe su operando derecho al flujo de salida especificado por su operando y devuelve el operando izquierdo como resultado.
La sentencia anterior se puede escribir tambin en dos partes:
cout << Hola programadores de C. << endl;
cout << endl;
aok.qxd
26/11/99 13:51
530
Pgina 530
void main ()
{
int fin = leer_num();
long total =0;
for (int i = 1; i <= fin; i++)
{
total += i;
cout << i= << i << total= << total << endl;
{
cout << *** total= << total << endl;
}
Tras estas consideraciones y comparaciones generales, pasemos a describir detalladamente todas las caractersticas y propiedades que mejoran C
mediante C++, el lenguaje diseado por Stroustrup.
A.4.
Para soportar programacin orientada a objetos, C++ introduce quince nuevas palabras reservadas que se aaden a las palabras reservadas de ANSI C.
Si desea compilar un programa en C con un compilador C++ se deben evitar el uso de las palabras reservadas especficas de C++. Estas nuevas palabras reservadas son:
asm
catch
class
delete
friend
inline
new
operator
private
protected
public
template
this
throw
try
virtual
volatile
A.5.
false
mutable
namespace
reinterpret_cast
static_cast
true
typeid
using
wchart_t
COMENTARIOS
C++ soporta dos tipos de comentarios. El mtodo tradicional, /* comentario*/ es ya conocido por los programadores de C. El compilador ignora todo
lo que viene despus de un smbolo /* y hasta que se encuentra con /*. Por
ejemplo, en este programa:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
/*
programa prueba
finalidad: visualizar enteros de 0 a 9
*/
#include <iostream.h>
int main()
{
int i;
for (i = 0;i < 10;i++)
cout << i << \n;
}
aok.qxd
26/11/99 13:51
Pgina 531
C FRENTE A C++
531
existe ms que durante el tiempo de ejecutar su bloque (sentencias entre llaves). Eso permite declarar dos variables diferentes de igual nombre en dos
bloques diferentes y separados como en el ejemplo siguiente:
/* comentario tradicional*/
A.6.
DECLARACIONES DE VARIABLES
double ds = sin(5.0);
ds *= ds;
{
double dc = cos(1.0);
dc *= dc;
}
}
if (test)
{
int i = 0;
// ...
}
else
{
long i = 5;
}
La posibilidad de declarar las variables en cualquier punto de un programa permite situarlas prximas a las sentencias donde se utilizan. El
siguiente programa muestra esta caracterstica:
#include <stdio.h>
int main()
{
int i;
for (i = 0; i < l00; ++i)
cout << i << /n;
double j;
for (i = 1.79154; j < 22..58131; j + = .001)
cout << y << endl;
}
aok.qxd
26/11/99 13:51
532
Pgina 532
//estilo C
double media (double num[100], int tamanyo)
{
int bucle;
double total = 0;
for(bucle = 0; bucle < tamanyo; bucle++)
total+= num[bucle];
return total/tamanyo;
}
A.6.1.
/* declaracin en C */
int main ()
{
int j;
cout << comienzo << endl;
for(j = 0; j < 100; j++)
{
int a;
cout << bucle << endl;
...
a = j;
...
}
}
//declaracin en C++
int main ()
cout << comienzo << endl;
...
for(int j = 0; j < 100; j++)
{
cout << bucle \ n;
...
int a = j;
...
}
}
aok.qxd
26/11/99 13:51
Pgina 533
C FRENTE A C++
A.6.2.
Declaraciones externas
Al contrario que C ANSI, C++ requiere que la palabra reservada extern sea
utilizada para especificar una declaracin externa especfica. En ausencia de
la palabra reservada extern, una sentencia de declaracin se considera
como una definicin. Obsrvese que una definicin de variable es equivalente a una declaracin de variable, excepto que la definicin asigna almacenamiento para la variable, mientras que una declaracin no lo hace. En
consecuencia, si
int a;
aparece fuera del cuerpo de una funcin, C ANSI lo considerar una declaracin mientras que C++ lo considerar una definicin. C++ indicar un
archivo que contiene dos declaraciones globales
533
}
ejemplo2 ()
{
int x, y;
{
int p;
}
}
// local a ejemplo2
// p, local a bloque interno
int a;
int a;
ejemplo1()
{
...
}
como un error.
En C, las sentencias anteriores se tratan como declaraciones equivalentes a:
ejemplo2()
{
...
}
extern int a;
extern int a;
define una variable entera cuenta, a la que se puede acceder tanto en ejemplol como en ejemplo2. Esta variable, como seguramente conoce el lector,
Slo la presencia de un valor inicial para una variable externa convierte una declaracin externa en C en una definicin; por ejemplo:
int a == 0;
A.6.3.
Las reglas de mbito de C++ y C son similares. Existen tres mbitos posibles para una variable u otro dato: local, file y class. Examinaremos
los mbitos local y file.
Una variable local se utiliza exclusivamente dentro de un bloque. Los
bloques se definen por una pareja de llaves:
ejemplo1 ()
{
int x, y;
...
aok.qxd
26/11/99 13:51
534
Pgina 534
El operador :: permite no utilizar la variable local, sino que se referencia a una variable de igual nombre fuera de su mbito. El programa anterior
visualizar:
cuenta interna = 10
cuenta externa = 5
Estilo C++
char *mensaje = Global;
...
void func()
{
char *mensaje = Local;
cout << mensaje;
//visualiza Local
cout << ::mensaje;
//visualiza Global
}
El operador de mbito se utilizar tambin en la definicin de las funciones (mtodos) de una clase para declarar la clase que pertenece a un
mtodo dado. El operador de mbito se puede utilizar para diferenciar entre
miembros de la clase base con nombres idnticos.
A.7.
const
const
const
const
longlista;
// correcto en ANSI C, no en C++
int longlista = 12000;
int m[] = {1,2,3,4,59};
char mensaje [] = Preparado;// array de caracteres
se debe escribir:
const EOF = -1;
const longmax = 128;
const pi = 3.14159;
Los nombres declarados con #define no tienen tipo, sin embargo, los
nombres declarados con const tienen tipo.
El compilador C++ siempre conoce el valor de una constante entera. El
siguiente fragmento de cdigo en C++ es aceptable, pero producir un error
en ANSI C:
const int buflon = 512;
char bufer[buflon];
//puntero a constante
//error
//correcto
aok.qxd
26/11/99 13:51
Pgina 535
C FRENTE A C++
Para hacer ambos objetos constantes deben ser declarados const. Por
ejemplo:
El modificador de tipo const se utiliza en C++ para proporcionar proteccin de slo lectura a variables y parmetros de una funcin. Las funciones miembro de una clase que no modifican los miembros dato a que
acceden se puede declarar const. Esto evita que estos miembros accedan a miembros dato no constantes. Tambin se utiliza para evitar que
parmetros pasados por referencia sean modificados.
void copias (const char*fuente, char*destino);
A.7.1.
535
// verdadero
// falso
// verdadero
// falso
aok.qxd
26/11/99 13:51
536
Pgina 536
LONGITUD = 40
2*LONGITUD = 100
#include <iostream.h>
void main()
{
char tab1[LONGITUD];
char tab2[2*LONGITUD];
int i;
char linea[LONG_INEA+1];
Se debe indicar el tipo asociado a la constante (int en el ejemplo anterior) y obligatoriamente inicializar la constante durante su declaracin,
ya que es imposible modificar el valor de una constante fuera de su inicializacin
Algunos ejemplos de declaraciones variable const y parmetros const:
const float pi= 3.1416;
const int max = 24;
const complex CD = (0.0, 0,0);
char *strcpy(char *s1, const char *s2);
const int *pn;
// estilo c++
// no permitido en C ANSI
A.7.2.
const indica al compilador que nunca cambia el valor del nombre. volatile indica al compilador que nunca conoce cundo cambiar el valor.
Se utiliza cuando se lee algn valor fuera del control del sistema, tal
como un registro en un soporte de hardware de comunicaciones. Una variable volatile se lee siempre que se requiere su valor, incluso si fue leda
justo en la lnea anterior. En el apartado A.12 ampliaremos este concepto.
A.8.
// f no devuelve un valor
// fr toma un puntero a un argumento int y
// no devuelve un valor
aok.qxd
26/11/99 13:51
Pgina 537
C FRENTE A C++
A.8.1.
sizeof ('m') == 1;
sizeof('A') == 2
sizeof('A') == 1
// En C
// En C++
// no es correcto
Punteros void
ANSI C permite que punteros de tipo void* sean asignados a cualquier otro puntero, as como cualquier puntero que sea asignado a un puntero de tipo void*.
C++ no permite asignacin de un tipo puntero void* a cualquier otro puntero
sin un molde explcito (cast). El siguiente ejemplo ilustra las diferencias:
void *p_void;
int i, *p_i;
p_void = &i;
p_i = p_void;
p_i = (int *)p_void;
A.9.
ciencia de C es la promocin automtica de todos los tipos char a int cuando se pasan a funciones o se utilizan en expresiones.
C++ ha eliminado estas limitaciones. Las constantes carcter en C++
son verdaderas constantes caracteres; en C++
int g();
void v;
537
unsigned char
signed char
char
A.9.1.
Inicializacin de caracteres
Es decir, en C clsico sizeof ('m') siempre produce el mismo resultado que sizeof (1) , que es 2 en implementaciones de 16 bts. Otra defi-
Despus de la inicializacin, los elementos del array nombre [0], nombre[1] y nombre[2] se fijarn a C, + y +, respectivamente. Sin embargo, C++
no permite este tipo de inicializacin, ya que el array no tiene espacio para el
carcter de terminacin nulo. En C++ , si se necesita establecer el array nombre como se hace en C, tiene que rescribir la inicializacin del modo siguiente:
char nombre[3] = {'C','+','+'};
// vlido en C y C++
aok.qxd
26/11/99 13:51
538
Pgina 538
int i = 0;
long l = (long)i;
long m = long (i);
// vlido en C y C++
A.10.
CADENAS
equivale a
double d = 3.9;
int i = 5,j;
j
j
d
d
=
=
=
=
i * (int)d;
i * int(d);
(double)i/ 7.0;
double(j)/ 7.0;
//estilo
//estilo
//estilo
//estilo
C ANSI
C++
C ANSI
C++
El segundo formato tipo (valor) suele ser ms fcil de leer. En C estndar, un puntero de tipo void* (es decir, un puntero hacia un objeto de tipo
indeterminado) se puede asignar a un puntero de cualquier tipo. En C++, la
conversin automtica de tipos o molde (casting) es obligatoria.
As, la funcin malloc devuelve un puntero de tipo void*, que se justifica debido a que malloc devuelve una direccin. En C estndar se puede
escribir:
Hola Mundo
y tambin
char *p;
p = malloc (100);
equivale a
char *p;
p = (char *) malloc (100);
ABCDEFGHIJKL
//estilo C ANSI
//estilo C++, no correcto en este caso
cout << Esta es una cadena que se considera una sola lnea;
A.11.
aok.qxd
26/11/99 13:51
Pgina 539
C FRENTE A C++
pc
pc
(char *)pi;
ptr_car(pi);
// estilo C ANSI
// estilo C++
539
{
while(!terminado)
...
//espera
A.12.
//espera
Este cdigo es posible que falle, o incluso peor, que falle dependiendo
de qu nivel de optimizacin se est seleccionando, ya que terminado no
est declarado voltil. Para permitir modificar datos, por ejemplo de modo
asncrono, es preciso declarar la variable terminado con el especificador
vo1atile, del siguiente modo:
A.13.
origen = {0,0};
caja[ 4]
*ptr_punto;
rect {punto origen; punto long;};
el nombre de typedef, trio en el ejemplo anterior, se utiliza como nombre del tipo.
aok.qxd
26/11/99 13:51
540
Pgina 540
A.13.2.
En C el fragmento de cdigo
struc prueba {int a; float b;};
struct prueba p;
Los mismos convenios se aplican a uniones. Sin embargo, para mantener compatibilidad con C, C++ acepta an la sintaxis antigua.
Estructuras y uniones
nombre_i
Un tipo especial de unin se ha aadido a C++. Denominada unin annima, declara simplemente un conjunto de elementos que comparten la misma
direccin de memoria. Una unin annima no tiene nombre de etiqueta
identificador y se puede acceder a los elementos directamente por nombre.
Este es un ejemplo de una unin annima en C++:
union
{
int i;
float f;
};
A.13.1.
Uniones annimas
Comparacin de C y C++
//Ejemplo en C
union prueba {
int x;
float y;
double z;
},
main()
{
union prueba acceso;
typedef union {
int Entero1;
char *bufer;
}Ejemplo;
acceso.x = 21;
acceso.y = 434.484;
acceso.z = 7.745;
}
Ejemplo Ex1
// declara unin;
El siguiente ejemplo se implementa en C++ y utiliza una unin annima para realizar la misma operacin.
aok.qxd
26/11/99 13:51
Pgina 541
C FRENTE A C++
int main()
{
union{
int x;
float;
double z;
};
x = 21;
y = 434.484; //el valor de y sobrescribe el valor de x
z = 7.745;
//el valor de z sobrescribe el valor de y
}
541
};
void test()
{
enum ventana w = saldo;
w--;
w = 3;
}
A.13.3.
void test ()
{
ventana w = saldo;
Enumeraciones
=
=
=
=
Primero;
Juan;
1;
Lugar(1);
//vlido
//vlido
//error
//vlido con cast.
((int &)w)--;
w = (ventana)3;
}
aok.qxd
26/11/99 13:51
542
Pgina 542
//estilo C ANSI
//estilo C ANSI
declaraciones de variables
dia d1,d2;
nodo n1,n2,n3;
// declaraciones de funciones
void visualizar_dia(enum dia d);
//estilo C ANSI
// declaraciones de funciones
void visualizar_dia(dia d);
nodo* encontrar_valor(nodo* n);
//estilo C ANSI
Cada vez que se utilizan estos tipos de datos pierde legibilidad el cdigo.
// declaraciones de nuevos tipos C ANSI
enum dia
{lunes,martes,mircoles,jueves,viernes,sbado,domingo};
typedef enum dia t_dia;
//estilo C++
//estilo C++
Enumeraciones annimas
El lenguaje C++ soporta la creacin de enumeraciones annimas (enumeraciones sin etiquetas). Tal entidad se declara quitando la etiqueta o nombre de
la enumeracin. El siguiente segmento de cdigo es un ejemplo de una
declaracin de enumeracin annima.
enum { Rojo, Verde, Azul, Amarillo };
Utilizado de este modo, las constantes enumerables se pueden referenciar de igual modo que las constantes regulares, como se muestra a continuacin:
struct nodo {
int valor;
struct nodo* izquierda;
struct nodo* derecha;
{;
A.13.4.
//estilo C++
//estilo C ANSI
//estilo C ANSI
A.14.
// declaracin de variables
t_dia d1,d2;
t_nodo n1,n2,n3;
// declaracin de funciones
void visualizar_dia(t_dia d);
t_nodo* encontrar_valor(t_nodo* n);
enum dia
{lunes,martes,mircoles,jueves,viernes,sbado,domingo};
struct nodo {
};
A.14.1.
main()
C no define un formato especfico para la funcin main. As, es tpico escribir la definicin de la funcin principal:
int valor;
nodo* izquierda;
nodo* derecha;
FUNCIONES EN C++
//estilo C++
//estilo C++
Sin embargo, main de C++ puede tomar una de las siguientes formas
(prototipos):
aok.qxd
26/11/99 13:51
Pgina 543
C FRENTE A C++
int main
int main(int argc,char *argv[])
En el segundo formato, argc representa el nmero de argumentos pasados al programa C++ desde la lnea de rdenes y argv[i] apunta al i-simo
argumento de la lnea de rdenes.
Al igual que en C, la terminacin de la funcin main termina el programa. La funcin main puede terminar con una llamada a la funcin exit
(con un argumento entero), alcanzando el final de su cuerpo, o ejecutando
la sentencia return. El argumento de la funcin exit es el valor devuelto
por el entorno. exit se llama normalmente con 1 para indicar fallo y con 0
si se indica xito. La terminacin de un programa por ejecucin de la sentencia return es equivalente a la terminacin del programa con la llamada
a exit.
#include <iostream.h>
int leer_nmero(1)
{
cout << Escribir un nmero
int n;
cin >> n;
//lectura de n
return n;
}
A.14.2.
// archivo FUNC1.CPP
543
Prototipos de funciones
Los prototipos encontrados en C ANSI han sido tomados de C + +. Un prototipo de funcin es una declaracin que define el tipo devuelto y el tipo y
nmero de parmetros de una funcin. El compilador utiliza el prototipo de
la funcin para asegurar que al menos se proporciona el nmero correcto y
los tipos de argumentos cada vez que se utiliza la funcin. En C tradicional,
las funciones se declaran as:
int test();
Esta declaracin significa que test es una funcin que devuelve un valor
entero (int)con dos parmetros, un puntero a carcter y un entero sin signo
(unsigned int). El compilador utiliza el prototipo para asegurar que los tipos
de los argumentos que se pasan en una llamada a una funcin son los mismos
que los tipos de los parmetros correspondientes. Esta propiedad se conoce
como verificacin estricta de tipos. Sin verificacin estricta de tipos es ms fcil
pasar valores ilegales a funciones. Una funcin sin prototipo permitir enviar
un argumento entero (int) a un parmetro puntero o utilizar un argumento
real (float) cuando espera un entero largo (long). Estas clases de errores
producen valores no vlidos para los parmetros de la funcin. Por otra parte,
cuando los tipos impropios se pasan a una funcin, el compilador no puede
restaurar la cantidad correcta del espacio de pila y su pila se puede romper.
Mientras que en ANSI C simplemante se utilizan prototipos, C++ los
requiere.
aok.qxd
26/11/99 13:51
544
Pgina 544
//estilo c++
int aleatorio(void);
// formato C++
int demo1();
int demo2(...);
Una funcin C++ que tiene una lista de parmetros abiertos requiere utilizar puntos suspensivos.
Recuerde que todas las funciones en C++ deben estar prototipadas. Esto
significa que cada funcin debe tener su lista de argumentos declarados, y
la definicin real de una funcin debe corresponder exactamente con su
prototipo en nmero y tipo de argumentos.
Los prototipos de funciones pueden significar un poco ms de trabajo cuando se escribe inicialmente un programa; sin embargo, los prototipos pueden tener un valor inapreciable en prevenir errores difciles de
encontrar. C++ fue diseado para prevenir muchos de los problemas del
programador imprudente que pasa tipos incorrectos a mtodos. Si realmente se necesita pasar un long como un int, se puede hacer utilizando
un molde (conversin forzosa de tipos). Algunos prototipos completos de
funciones:
int f1(void);
//devuelve un tipo int, no toma argumentos
void f2();
//como f4 () en c++ pero no en ANSI C
float f3(float, int, char, double);
// devuelve float
void f4(void); // no toma argumentos, devuelve nada
Prototipo
Formato C
Formato C++
f (void);
int f (void)
void f (void);
int f ();
int f () ;
no verificar argumentos de
funcin
int f(...);
no toma argumentos
int f(...);
A.14.3.
El lenguaje C++ es ms estricto que el ANSI C en los tipos de datos manipulados. En consecuencia, C++ impone declarar el nmero y tipo de argumentos que recibe una funcin, as como el tipo de valor devuelto. Estas
declaraciones son similares a los prototipos de funciones de la norma ANSI,
merced a los cuales el compilador puede verificar la coherencia de su cdigo fuente entre las declaraciones de las funciones y sus llamadas efectivas.
Sin embargo, mientras que la utilizacin de prototipos es opcional en ANSI
C, son obligatorios en C++ para que un programa sea aceptado por el compilador.
aok.qxd
26/11/99 13:51
Pgina 545
C FRENTE A C++
// Archivo PROTO1.CPP
#include <iostream.h>
void discriminante(a, b, c);
double a, b, c;
{
double d;
d = b*b-4*a*c;
visualizar(d);
545
La declaracin de un prototipo de funcin no debe necesariamente llevar los nombres de los argumentos formales de la funcin, sino nicamente
sus tipos. As, las dos declaraciones siguientes son equivalentes:
}
void visualizar(d)
double d;
{
cout << Discriminante = << d << endl;
}
void main ()
cout << Teclear a b c;
double a, b, c;
cin >> a >>b >> c;
discriminante(a, b, c);
{
A.14.4.
//Archivo PROTO2.CPP
#include <iostream.h>
void visualizar(double d);
//declaracin de prototipo
Funciones en lnea
//vlida
}
// Utilizacin de estilo C++ y C ANSI
void visualizar(double d)
{
cout << Discriminante =
}
void main ()
Esta funcin no existe realmente como una funcin que se pueda llamar.
En su lugar, el compilador inserta el cdigo que realiza su tarea siempre que
aparece una llamada a suma en su programa. Los traductores de C crean
macros para las funciones en lnea e insertan esas macros en el programa C
resultante y apunta dnde es llamada la funcin. Un compilador C++ precompila la rutina e inserta las instrucciones precompiladas en las posiciones
apropiadas.
Existen algunas reglas para utilizar funciones en lnea. Las funciones en
lnea deben ser definidas antes de que puedan ser utilizadas. Esto se debe a
que el cdigo para la funcin en lnea debe ser precompilado antes que se
aok.qxd
26/11/99 13:51
546
Pgina 546
class Rect
public:
Rect ();
Rect ();
int izquierda()
int derecha()
int cima()
int fondo()
private:
int x, y;
int anchura, altura;
};
A.14.5.
//Archivo : Mathlocal.h
//Prototipos (declaraciones de funciones)
inline int alos (int i);
inline int min (int v1, int v2);
int mcd (int v1, int v2);
Las funciones declaradas en lnea deben ser sencillas, con slo unas
pocas sentencias de programas. Deben ser llamadas slo un nmero limitado de veces y no deben ser recursivas.
Las funciones miembro declaradas con una definicin en la especificacin de la clase se consideran automticamente en lnea por el compilador:
return
return
return
return
x; }
x + anchura; }
y; }
y + altura;}
Las funciones en lnea son como macros del preprocesador, ya que el compilador sustituye el cuerpo de la funcin completo para cada llamada a una
funcin en lnea. Las funciones y las macros difieren esencialmente en
aspectos fundamentales:
Al contrario que a las macros, el compilador trata a las funciones en lnea
como funciones verdaderas.
{
{
{
{
aok.qxd
26/11/99 13:51
Pgina 547
C FRENTE A C++
Por consiguiente:
defecto(5,6)
defecto(10,6)
defecto(10,20)
ventana v;
En C++ existe otra mejora a las funciones en C, es que se pueden especificar los valores por omisin para los argumentos cuando se proporciona un
prototipo de una funcin. Es decir, determinados argumentos se pueden
omitir e inicializar a un valor por defecto u omisin, y a continuacin omitir el argumento real en la llamada. La sintaxis es la siguiente:
defecto()
es igual que
defecto(10)
es igual que
defecto(10,20) es igual que
Examinemos el ejemplo siguiente. Se define una funcin crear_ventana que establece una ventana (una regin rectangular) en una pantalla de
una llamada a
una llamada a
una llamada a
producto de 5 y 6 = 30
producto de 3.1 y 10.0 = 31.000.000
A.14.6.
547
aok.qxd
26/11/99 13:51
548
Pgina 548
corresponde con y, etc. Por consiguiente, slo se pueden dejar los argumentos finales de la lista sin especificar, y adems se tienen que inicializar
todos de derecha a izquierda y consecutivamente:
//prototipo con error
void mackoy(int a=1, int b, int c=3, int d=4);
//prototipo vlido
void makena(int a, int b=2, int c=3, int d=4);
main()
{
f(4,5);
f(6);
}
void f(int i, int j)
{
cout << i: << i << y j: << j << endl;
}
}
void visualizar(const int a[], int n, int cuenta)
{
int i;
for (i = 1; i <= n; i++)
{
cout << a[i-11];
if (i%cuenta == 0 | | i == n)
cout << \n;
else if (i! = 0)
cout << ;
}
}
Comentario
Primer argumento (array a visualizar). Segundo argumento (nmero de elementos del array). Tercer argumento (nmero de elementos a visualizar en
cada lnea, por omisin = l).
La salida es:
i : 4 y j : 5
i : 6 y j : 2
El programa ARGOMI.CPP utiliza argumentos por omisin en las llamadas sucesivas a la funcin visualizar.
//Prueba de argumentos por omisin: ARGOMI.CPP
//Programa C++ que impone un array con diferentes elementos
//por lnea
A.14.7.
aok.qxd
26/11/99 13:51
Pgina 549
C FRENTE A C++
indica que func se definir de tal forma que las llamadas deben tener al
menos dos argumentos, uno int y otro char, pero pueden tener tambin
cualquier nmero de argumentos adicionales. En C++ se puede omitir la
coma que precede a los puntos suspensivos.
Los puntos suspensivos pueden tomar cualquiera de los dos formatos en
las correspondientes llamadas:
func(lista_arg,...);
func(...);
Esta caracterstica se encuentra en C, aunque normalmente no se piensa en ella. Sin embargo, un ejemplo claro de aplicacin de esta propiedad se
encuentra en la funcin printf(), que permite utilizar funciones con un
nmero variable de parmetros en C. C++ soporta tambin esta funcin,
cuyo prototipo recordemos es
printf(const char*...);
especifica una funcin que requiere dos argumentos enteros y un argumento double y un nmero adicional de argumentos que es desconocido en
tiempo de compilacin.
Un buen ejemplo de funciones con nmeros variables de argumentos es la
familia de funciones printf definidas en el archivo de cabecera <stdio.h>.
int fprintf(FILE *flujo, const char * formato, ...);
int printf(const char *formato, ...);
int sprintf(char *buffer, const char *formato, ...);
A.15.
LLAMADA A FUNCIONES C.
PROGRAMAS MIXTOS C/C++
extern C {
typedef struct {
float r, i;
} complex;
complex
nuevocomplejo(float x, float y);
float
real(complex a);
f(valor);
f (xyz, a, b, c);
549
float
float
extern C {
char *memcpy(char *t, char *s);
int strlen(char *t);
}
aok.qxd
26/11/99 13:51
550
Pgina 550
en \BORLAND\INCLUDE;
#ifdef _cplusplus
extern C {
#endif
void _Cdecl...
...
#ifdef _cplusplus
}
#endif
A.16.
EL TIPO REFERENCIA
En C, cuando se llama a una funcin con argumentos, los valores de los argumentos se copian en una rea especial de memoria conocida como la pila. La
funcin utiliza estas copias para su operacin. Este efecto se denomina llamada por valor. Para ver este efecto, consideremos el siguiente cdigo:
void dosveces(int a)
{
a *= 2;
}
...
int x = 5;
...
int x= 5;
// llamada a dosveces con la direccin de x como argumentos
dosveces(&x); printf(x=%d\n,x);
//suma 10 a i
& a)
dosveces (x);
cout << x= << x << endl;
aok.qxd
26/11/99 13:51
Pgina 551
C FRENTE A C++
551
ellos.
// estilo C
#include <iostream.h>
int& max(int &a, int &b)
{
if (a>b)
return a; return b;
}
void main
{
int x = 20, y = 30;
max(x,y)--;
cout << x << y << endl;
}
void intercambio(int
{
int aux;
aux = *a;
*a = *b;
*b = aux;
}
...
//llamada a la funcin intercambio
intercambio(&i1, &i2);
29
// estilo C++
Una referencia ordinaria se debe inicializar con alguna variable del tipo
apropiado. Por ejemplo, una referencia a un tipo double se debe inicializar
con una variable double:
double di;
double &rd1 = di;
#include <iostream.h>
int main()
{
void intercambio(int &xptr, int &yptr);
int s = 10, t = 20;
// error
aok.qxd
26/11/99 13:51
552
Pgina 552
intercambio(s,t);
cout << Despues de intercambio, s= << s << , t= << t << endl
;
return 0;
}
void intercambio(int &x, int &y)
{
int aux;
aux = x;
x = y;
y = aux;
}
A.17.
SOBRECARGA
La funcin ref aceptar un valor entero (datosuno) pasado por referencia, pero, dado que tiene definido const, significar que no se puede
cambiar. El calificador const permite utilizar referencias eficientes sin
sacrificar integridad de los datos.
Como ya se ha comentado, aunque las referencias son muy similares a
los punteros, no son punteros. No se pueden utilizar para asignar memoria
dinmica, ni se pueden manipular matemticamente. El propsito final de
las referencias es permitir que las funciones cambien sus argumentos y que
acepten estructuras y objetos como parmetros de un modo ms claro.
aok.qxd
26/11/99 13:51
Pgina 553
C FRENTE A C++
caractersticas son muy potentes y exigen un conocimiento juicioso y prudente por parte del programador.
A.17.1.
Sobrecarga de funciones
Otro ejemplo de funcin sobrecargada es sort, que ordena arrays o listas de diferentes tipos:
void
void
void
void
double calcular(int)
float calcular(int)
553
int suma(int i)
{
return i + 42;
}
main()
{
int i = suma (42, 17);
double d = suma(42.0, 17.0);
char s1 [] = abc;
char s2 [] = xyz;
suma (s1, s2);
}
aok.qxd
26/11/99 13:51
554
Pgina 554
A.17.2.
La funcin visualizar escribe cualquier tipo de objeto en la salida estndar: una versin visualiza un tipo empleado, otra versin una cadena, otra
un tipo int, etc. Para conseguir esta caracterstica se sobrecarga la citada
funcin.
//nmero de empleado
//nombre y nmero de telfono
//edad de empleado
int main()
{
empleado emp;
emp.numero = 1001;
emp.edad = 46;
//rellenar info de empleado
emp.nombre = Mark Mackoy;
emp.telefono = 99-4374220;
visualizar(emp);
//escribir un empleado
return 0;
}
void visualizar(const empleado &e)
{
visualizar(Empleado: ); visualizar(e.numero);
visualizar(\n);
visualizar(Nombre:
); visualizar(e.nombre);
visualizar(\n
);
visualizar(Edad:
); visualizar(e.edad);
visualizar(\n);
visualizar(Telefono: ); visualizar(e.telefono)
visualizar(\n);
}
void visualizar(char *s)
{
cout *s;
}
void visualizar(int i)
{
cout << i;
}
void visualizar(long 1)
{
cout << 1;
}
aok.qxd
26/11/99 13:51
Pgina 555
C FRENTE A C++
555
}
void visualizar(const char * s) {
cout << s;
}
void visualizar(const int i){
cout << i;
}
void visualizar (const long 1) {
cout << 1;
}
//FICHERO: empleado.h
//FICHERO (ARCHIVO): principa.cpp
#ifndef EMPLEADO
#define EMPLEADO
#include empleado.h
int main() {
empleado emp;
struct empleado {
long numero;
char * nombre;
char * telefono;
int edad;
};
void
void
void
void
visualizar(const
visualizar(const
visualizar(const
visualizar(const
emp.numero = 1001;
emp.edad = 46;
emp.nombre = Mark Mackoy;
emp.telefono = 91-437422011;
empleado & e);
char * s);
int i);
long l);
visualizar(emp);
return 0;
}
#endif
//FICHERO(ARCHIVO): empleado.cpp
#include empleado.h
#include <stdio.h>
void visualizar(const empleado & e){
visualizar(Nmero:);
visualizar(e.numero);
visualizar(\n);
visualizar(Nombre:);
visualizar(e.nombre);
visualizar(\n);
visualizar(Telfono:);
visualizar(e.telefono);
visualizar(\n);
visualizar(Edad:);
visualizar(e.edad);
visualizar(\n);
A.17.3.
Sobrecarga de operadores
Al igual que C++ permite definir diferentes funciones con el mismo nombre
pero con variacin en sus argumentos, tambin permite redefinir el significado de operaciones tales como +, , *, %, + =, =, ..., para cualquier clase.
En otras palabras, se puede sobrecargar el significado de los operadores. La
sobrecarga de operadores es un concepto interesante que en la mayora de
los lenguajes existe, aunque adquiere su mxima potencia en C + +
As por ejemplo, se pueden sumar dos enteros utilizando el operador +:
a = 5 + 2;
aok.qxd
26/11/99 13:51
556
Pgina 556
//Estilo C ANSI
//Estilo C++
int *ptr;
*ptr = 5;
A.18.
A.18.1.
El operador new
El operador new es ms sencillo de utilizar que la funcin malloc() cuando los tipos de las variables a asignar dinmicamente se vuelven complejas.
Compare en el ejemplo siguiente la sintaxis de las asignaciones de memoria que utilizan malloc() y la sintaxis de las que utilizan new.
*nudoN;
//Asignacin de un nudo
nudo1 = (nudo*) malloc (sizeof(nudo)); //Estilo C ANSI
nudo1 = new nudo;
//Estilo C++
// Asignacin de N nudos
int N;
cout << cuantos nudos:?;
cin >> N;
nudoN = (nudo*) malloc(N*sizeof(nudo)); //Estilo C ANSI
nudoN = new nudo[N]
//Estilo C++
aok.qxd
26/11/99 13:51
Pgina 557
C FRENTE A C++
...
p = (int *) malloc (20 * sizeof(int));
...
free(p);
557
Mtodo C
int *P=(int*) malloc (sizeof (int));
Mtodo C++
A.18.2.
El puntero nulo/cero
A.18.3.
El operador delete
El operador delete libera la memoria asignada con new. Este operador funciona de modo similar a la funcin free() para la memoria asignada con
malloc(). No se puede utilizar free()sobre un puntero inicializado con
new, ni delete sobre un puntero inicializado con malloc(). Los formatos
de delete son:
delete direccion
que asigna almacenamiento para un tipo entero (int), inicializa el almacenamiento a 0 y a continuacin guarda un puntero al almacenamiento en la
variable ptri.
delete []direccion
aok.qxd
26/11/99 13:51
558
Pgina 558
// archivo deletenew.cpp
void main()
{
double *d;
d = new double;
//Asignacin de un solo objeto
*d = 12.34;
delete d;
//Liberacin de un solo objeto
d = new double[10];
//Asigna un array de objetos
for(int i=0; i>10; i++)
d[i] = double(i) / 7.0;
delete[]d;
//Liberacin de un array de objetos
//Estilo C
struct Paciente
char nombre [20]
char sexo;
unsigned id;
};
struct Paciente *p;
p = (struct Paciente));
malloc (size(Paciente));
/* ... */
free (p);
//Estilo C++
struc Paciente {
char nombre [20];
char sexo;
unsigned id;
};
struct Paciente *p;
p = new Paciente;
//...
delete p;
El operador delete simple se utiliza para liberar la memoria asignada a un nico objeto, y el operador delete [] cuando se asigna un array o
tabla de objetos. En este ltimo caso no es necesario precisar el nmero de
objetos inicialmente asignados.
Los operadores new y delete sustituyen ventajosamente a las funciones
malloc() y free() para todos los problemas de asignacin dinmica de
memoria. Sin embargo, estos operadores alcanzan su mayor rendimiento en la
gestin correcta de clases en C++, autorizando la inicializacin de un objeto
que pertenece a una clase despus de la asignacin dinmica de ese objeto.
A.18.4.
int *p = new(int);
int *p = new int[10];
Aunque new es til para asignar memoria a variables de tipos incorporados, la potencia real reside en asignar objetos dinmicos que tienen constructores. Cuando new se utiliza para tales objetos, entonces se llama
automticamente uno de los constructores.
reloj *r = new reloj(12,30,45); // asigna e inicializa
delete libera memoria dinmica asignada por new:
int *p = new int;
delete p;
reloj *r = new reloj(4,15,55); //asigna reloj
delete reloj;
//libera reloj
delete produce una llamada al destructor en este orden:
1. El destructor se llama.
2. La memoria se libera.
delete es ms segura que free(), ya que protege al intentar liberar
memoria apuntada por un puntero nulo.
A.19.
Un programa C++ se construye sobre la base de archivos .cpp y .h, estructurados sobre la base de un archivo principal de la funcin main, con extensin .cpp.
Archivo principal: nomina.cpp
#include empleado.h
...
main ()
{
...
}
aok.qxd
26/11/99 13:51
Pgina 559
C FRENTE A C++
//nomina.cpp
#include empleado.h
...
main()
{
...
}
A.19.1.
En cada archivo de cabecera que tiene una clase se debe verificar, en primer
lugar, que el archivo no ha sido ya incluido en este archivo. Esto se realiza
mediante un indicador (macro) del preprocesador. Si el indicador no est activado, el archivo no se incluye; se debe activar el indicador y declarar la clase.
Si el indicador est activado, la clase ha sido ya declarada, de modo que se
ignora el cdigo que declara la clase. El archivo de cabecera ser similar a ste:
#ifndef INDICADOR_CLASE
#define INDICADOR_CLASE
//Declaracin de la clase
#endif INDICADOR_CLASE
Como se puede ver, la primera vez que el archivo de cabecera se incluye la declaracin de la clase se incluir por el procesador, pero se ignorar
la definicin de la clase en todas las siguientes ocasiones.
El nombre de la macro o indicador puede ser cualquier nombre nico,
pero un mtodo fiable a seguir es tomar el nombre del archivo de cabecera
de sustituir el punto de la extensin por un subrayado y aadir delante o despus del indicador o macro una H (de header) y un subrayado, o cualquier
otra palabra similar que recuerde el nombre del archivo de cabecera.
//archivo de cabecera: PRUEBA.H
#ifndef PRUEBA_H_
#define PRUEBA_H_
class uno {
int i, j, k;
public :
llamar() {i = j = k = 0;}
};
#endif //PRUEBA_H_
Archivo principal
559
as:
#ifndef NOMBRE_CLASE
#define NOMBRE_CLASE
//especificacin de la clase
//que slo incluir el archivo fuente una vez
#endif
#include nombre.h
//utiliza la clase Nombre
class Persona {
//especificacin de la clase
};
#include nombre.h
//utiliza la clase Nombre
class Coche {
//especificacin de la clase
};
A.19.2.
//empleado.h
#ifndef H_EMPLEADO
#define H_EMPLEADO
class empleado{
private:
int id;
aok.qxd
26/11/99 13:51
560
Pgina 560
...
public:
empleado(int i, char *n, float w);
...
};
public:
empleado(int i, char *n, float s);
void ver_salario(float horas);
};
#endif
//empleado.cpp, implementaciones
#include <stdio.h>
#include <string.h>
#include empleado.h
empleado :: empleado(int i, char *n, float s);
{
id = i;
strcpy(nombre,h);
tasa = s;
}
void empleado :: ver_salario(float horas)
{
cout<< Empleado: << id << : << nombre << endl;
cout << Horas trabajadas: << horas << endl;
cout << Cantidad pagada: << horas*tasa << endl;
}
#include empleado.h
int main ()
{
empleado mortimer(1, juan mortimer,1500);
empleado mackoy(2, pepe mackoy,2200);
mortimer.ver_salario(400);
mackoy.ver_salario(5200);
return 0;
}
aok.qxd
26/11/99 13:51
Pgina 561
C FRENTE A C++
561
RESUMEN
C++ es una extensin del lenguaje C, que se conoci en sus orgenes con el nombre
de C++ con clases. El inventor de C++, Bjarne Stroustrup, denomin a C++ a
better C (un C mejor).
La mayor atribucin al mundo de la programacin de C++ ha sido la clase.
Adems, C++ ha aadido a ANSI C nuevas palabras reservadas y operadores, funciones en lnea y sobrecargadas, operadores sobrecargados, nuevas tcnicas de gestin de memoria y otras caractersticas complementarias.
En la actualidad, la versin que ha sido estandarizada por el comit ANSI es la
EJERCICIOS
A.1. Explicar cul es la razn por la que el siguiente programa se detiene con un
mensaje Divide error:
//errordiv.cpp
#include <stdio.h>
int valor;
main ()
{
int n = 100/valor;
printf ("n = % da n",k);
return 0;
A.2. Escribir un programa que solicite un nombre, a continuacin, visualice el mensaje Hola seor/seora x, donde x es reemplazada por el texto introducido.
A.3. Escribir un programa que solicite un nmero entero con signo, a continuacin
visualice el nmero equivalente sin signo en cdigo decimal y hexadecimal.
A.4. Escribir un programa que determine si un nmero entero es par o impar.
A.5. Escribir un programa que solicite un nmero entre 1 y 100. Si se introduce un
nmero de valor fuera de rango, el programa debe visualizar un mensaje de
error y volver a solicitar la introduccin de un nmero.
A.6. En matemticas, el factorial de n (Nmero entero no negativo) se define
mediante la ecuacin:
n! = 1 * 2 * 3 * ... * n;
S = 4 r 2
Escribir un programa que solicite repetidamente introducir parejas de nmeros, hasta que al menos un nmero de la pareja sea cero. Por cada pareja, el
programa debe utilizar una funcin para calcular la media armnica de los
nmeros.
Media armnica = 2.0 * x * y /(x + y)
A.10.Escribir una funcin que calcule la longitud de una cadena que es un argumento.
A.11. Disear y escribir una funcin que haga notar una serie de valores de una lista
una posicin a la derecha. Es decir, dados los valores 10, 11, 12, 13, 14, la llamada a la funcin cambia la lista a 14, 10, 11, 12, 13, una nueva llamada cambia a 13, 14, 10, 11, 12, etc.
aok.qxd
26/11/99 13:51
562
Pgina 562
A.12. Escribir una funcin que devuelva la moda de una serie de valores reales
(double) almacenados en un array.
A.13. Declarar una estructura que represente un nmero de telfono (cdigo del
pas, cdigo del rea prefijo provincial y nmero). Declarar asimismo
una estructura anidada con dos nmeros de telfono: una para comunicacin
por voz y el otro para fax.
Definir un array que contenga 50 estructuras del tipo nmero de telfono.
A.14. Escribir una funcin que tome un argumento, la direccin de una cadena e
imprima la cadena una vez. Si se proporciona un segundo argumento int y
no es cero, la funcin imprime la cadena un nmero de veces igual al nmero de veces que la funcin ha sido llamada en ese punto.