Estructura C++

También podría gustarte

Está en la página 1de 23

1

Apéndice II
Guía de sintaxis del lenguaje
ANSI/ISO C++ estándar
v1*
EL LENGUAJE DE PROGRAMACIÓN C++
C++ es considerado un C más grande y potente. La sintaxis de C++ es una extensión de C, al que se han
añadido numerosas propiedades, fundamentalmente orientadas a objetos. C ANSI 1 ya adoptó numerosas
características de C++, por lo que la emigración de C a C++ no suele ser difícil.
En este apéndice se muestran las reglas de sintaxis del estándar clásico de C++ recogidas en el Annotated
Reference Manual (ARM), de Stroustrup & Ellis, así como las últimas propuestas incorporadas al nuevo
borrador de C++ ANSI, que se incluyen en las versiones actuales de AT&T C++.

EL PRIMER PROGRAMA C++


Cada programa C++ contiene una o más funciones, una de las cuales se denomina main(). Una
función consta de una o más sentencias que ejecutan el trabajo de la función. El sistema operativo
ejecuta un programa llamando a la función main(); esta función ejecuta sus sentencias y devuelve
un valor al sistema operativo.

El sistema operativo utiliza el valor devuelto por main() para determinar si el programa ha tenido o
no éxito. Un valor de retorno 0 indica éxito. La función main() debe existir en cada programa C++ y
es la única función que llama explícitamente el sistema operativo.
Un programa C++ completo que visualice la frase en español "Hola mundo"es
// programa hola.cpp
// el programa visualiza "Hola mundo"
#include <iostream> // declaraciones
using namespace std;
int main() // función main( )
{
// visualizar "Hola mundo"
cout<< "Hola mundo!" << endl;
return 0;
}
La directiva using namespace std define el espacio de nombres std y evita tener que utilizar esta
directiva. Si no se utiliza el espacio de nombres using namespace std la salida con cout requerirá
ser precedida por el espacio de nombre std.
* Fuente: Programación en C/C++, Java y UML, 2ª ed. Joyanes-Zahonero, 2014 (páginas 596-737)
2

#include <iostream> int main ()


{
// visualizar "Hola mundo"
std::cout<< "Hola mundo" << std::endl;
return 0;
}

El programa hola.cpp contiene los siguientes elementos:


• Comentario, indicados por la doble barra //
• Directiva del prepocesador #include
#include <iostream>
Se necesita para todas las declaraciones de entrada y salida.
• Cabecera de la función: int main().
• Una directiva using namespace.
• Un cuerpo de la función separado por { y }.
• Sentencias que utilizan cout para visualizar un mensaje.
• Una sentencia return para terminar la función main( ).
Comentarios en C++
Además del estilo de comentarios propios de C++
// Esto es un comentario

Es posible escribir en programa comentarios estilo C


/* este es un comentario
en varias líneas de programa */

El preprocesador de C++ y el archivo iostream


La primera línea de programa
#include <iostream>
Se denomina directiva del preprocesador, que es una directiva del preprocesador que es una instrucción
al compilador. El preprocesador es una parte de compilador que procesa un archivo fuente antes de
que tenga lugar la compilación. La directiva #include es reemplazado por el contenido del archivo
indicado. El tipo de archivo incluido normalmente por #include se denomina archivo de cabecera.
Los nuevos archivos de cabecera de ANSI C++ estándar no tienen una extensión .h como los antiguos
archivos de compilador C++.
#include <iostream>
Entrada y salida
C++ no define directamente ninguna sentencia para realizar las operaciones de entrada y salida (E/S).
La E/S la proporciona la biblioteca estándar. La biblioteca de E/S suministra un conjunto amplio de
facilidades. La directiva
#include <iostream>
añade el contenido del archivo de cabecera <iostream> para E/S. iostream manipula entrada y
salida con formatos. La biblioteca iostream tiene dos tipos: istream y ostream que representan los
flujos de entrada y salida. Un flujo (stream) es una secuencia de caracteres empleada para leer de un
dispositivo o escribir en un dispositivo de E/S (el término flujo se refiere al hecho de que los caracteres
se generan o conducen secuencialmente uno a uno).
Las características de E/S se consiguen insertando la sentencia #include <iostream>. Con la
inclusión de la declaración anterior se definen los siguientes símbolos.
3

Símbolo Significado
std::cin canal de entrada estándar (teclado)
std::cout canal de salida estándar (pantalla)
std::cerr canal de salida de error (pantalla)
std::endl símbolo para avance de línea

La entrada se realiza a través de un canal estándar, que se asigna generalmente al teclado. La


salida se hace a través de otro canal estándar que se asigna por lo general a la pantalla. Ambas pueden
ser redirigidas por el sistema operativo o utilizando funciones del sistema, de modo que, por ejemplo,
la salida estándar se escriba en un archivo.
Los datos se envían al canal de salida utilizando el operador << y se pueden encadenar múltiples
salidas
#include <iostream>
std:: cout<< "poner un número" << 45 << std::endl;

endl es una instrucción especial de C++ que significa “comienzo de nueva línea”. La inserción
de endl en el flujo de salida hace que el cursor de la pantalla se mueva al principio de la siguiente
línea. Por ejemplo, cout << " Hola!! " << endl; otra forma de indicar nueva línea es con el
carácter '\n', por ejemplo, cout << " \n " equivale a cout << endl.

Ejemplo

Regla
cout << "Introducir dos números"; visualiza texto
cin >> n1 >> n2; entrada de dos datos

Archivos de cabecera
La directiva #include indica que se desea utilizar la biblioteca iostream y que se debe añadir el
archivo fuente iostream al archivo fuente del programa antes de comenzar la compilación.
Los archivos como iostream se denominan también archivos de inclusión (include) ya que se adjun-
tan en otros archivos o bien archivos de cabecera (header), ya que ellos se incluyen al principio de un
archivo. Los compiladores de C++ vienen con muchos archivos de cabecera que soportan un amplio
conjunto de propiedades y características.
Regla
La directiva #include se debe escribir en una sola línea; el nombre del archivo de cabecera e inclu-
de deben aparecer en la misma línea. En general, las directivas #include aparecerán fuera de cual-
quier función; normalmente, todas las directivas #include de un programa aparecen al principio del
archivo.

ESPACIOS DE NOMBRES
C++ estándar tiene la característica de espacios de nombre, que permite facilidades para nombrar a
variables, funciones, estructuras, clases, enumeraciones, etc. y que no se produzcan conflictos en
dichos nombres.
4

Los espacios de nombres proporcionan un mecanismo para controlar la colisión de nombres ya


que cada nombre definido en un ámbito dado debe ser único dentro de ese ámbito. Un espacio de
nombres comienza con la palabra reservada namespace seguida del nombre del espacio.
En C++ existe un espacio de nombres estándar, std en la biblioteca iostream de
entrada y salida. De este modo se utiliza std::cout y std::endl en lugar de cout y endl.
El prefijo std:: indica que los nombres cout y endl estan definidos en el espacio de
nombres std.
El símbolo :: se denomina operador de resolución de ámbito o (alcance), y se emplea, entre
otros casos, para salida (cout), entrada (cin), y para fin de línea.
std::cout utiliza el nombre cout definido en el espacio de nombre std

std. std::cin >> v1 lee la entrada de v1 utilizando cin definido en std.

Regla 1
Si se usa el archivo <iostream> se necesita utilizar el espacio de nombre std para E/S
#include
<iostream> int
main ( )
{
std::cout<< "¡Hola mundo!" << std::endl;
return 0;
}

Sin embargo, es posible otro estilo de escritura que requiera el uso de std:: cuando se utiliza el archivo
iostream. Este estilo de escritura requiere el uso de la directiva using que permite disponer las
definiciones de iostream en sus programas. Si desea utilizar este método similar al estilo iostream.h
debe incluir en sus programas

#include <iostream>
using namespace std;
Ejemplo
include <iostream>
using namespace std;
int main ( )
{
cout<< "¡Hola mundo!" << endl;
}

TIPOS DE DATOS NATIVOS


C++ proporciona un conjunto de tipos de datos predefinidos y operadores que manipulan los tipos de
datos. C++ puede definir un número de tipos de datos, pero no especificar su tamaño. El tamaño
dependerá del sistema operativo y de la plataforma sobre la que se ejecute su programa. Los siguientes
tipos de datos están predefinidos:
• Tipos de entero.
• Tipos de coma flotante.
• Tipos lógicos.
• Tipos carácter.
• Tipos referencia.
• Tipos enumeraciones.
• Tipos arreglo (array).
• Nombres de tipos definidos por el usuario.
• Otros tipos compuestos
5

Tipos de datos básicos/primitivos


C++ define un conjunto de tipos aritméticos: enteros, coma flotante, carácter individual y valores
lógicos (boleanos). Además, existe un tipo denominado void. El tipo void no tiene valores asociados
y solo se puede utilizar en un conjunto limitado de circunstancias; usualmente se utiliza como el tipo
de retorno de una función que no devuelve ningún valor.

Tabla 16.2 Tipos aritméticos en C++.

Tipo Significado Tamaño mínimo


bool boolean (lógico) 1 bit
char carácter 8 bits
wchar_t carácter ancho 16 bits
short entero-corto 16 bits
int entero 16 bits
long largo-entero 32 bits
float real simple precisión 6 dígitos significativos
double real doble precisión 10 dígitos significativos
long double real doble precisión extendido 10 dígitos significativos

.3 Tipos integrales.

Tipo Significado
int entero (tamaño de palabra típica de la máquina)
short valor más pequeño que el normal
long valor mayor que el normal
bool número lógico o boolean (verdadero/falso)

.4 Tipos con signo.


int, short, long con signo por defecto
unsigned int, o unsigned entero sin signo
unsigned long long con signo
char con signo por defecto
signed char con signo
unsigned char char sin signo

Tipos de coma flotantes (reales)


Los tipos float, double y long double representan valores de coma flotante de simple y de doble
precisión. Normalmente, float representa una palabra (32 bits), double representa dos palabras (64
bits) y long double, representa tres o cuatro palabras (96 o 128 bits).
El tamaño del tipo determina el número de dígitos significativos que un valor de coma flotante
puede contener (normalmente float, 6 dígitos significativos y double, 10 dígitos significativos).

Tipos apuntadores (punteros)


Los apuntadores (punteros) referencian a datos. Una variable apuntador contiene una dirección
6

como su valor en memoria y “apunta” a otra variable, objeto o incluso función.


Los operadores & y * se utilizan en el diseño de apuntadores.
• El operador unitario & produce la dirección de un valor o un apuntador a valor.
• El operador unitario * desreferencia un apuntador, que significa lo que se devuelve y
sirve para declarar el apuntador.

OPERADORES
C++ proporciona un conjunto muy rico de operadores y define cuáles de estos operadores se aplican
a tipos fundamentales. Una expresión se compone de uno o más operandos que se combinan mediante
operadores. La forma más simple de una expresión consta de una sola constante literal o variable. Las
expresiones más complejas se forman con un operador y uno o más operandos. Cada expresión
produce un resultado.
Existen operadores unitarios que actúan sobre un solo operando (operador dirección &; operador
de referencia *) y operadores binarios y terciarios, que actúan sobre dos o tres operandos (suma +,
resta –). Los operadores se clasifican en función de las tareas que ejecutan: aritméticos, relacionales,
lógicos, etc.

16.5 Operadores aritméticos.

Operador Función Ejemplo

+ más unitario + expr


− menos unitario − expr
* multiplicación a*b
/ división a/b
% resto (módulo) a%b
+ suma a+b
− resta a−b
7

Tabla 16.6 Operadores relacionales y lógicos.

Operador Función Ejemplo

! NOT lógico !expr


< menor que expr1 < expr2
<= menor o igual que expr1 <= expr2
> mayor que expr1 > expr2
>= mayor o igual que expr1 >= expr2
== igualdad expr1 == expr2
!= desigualdad expr1 != expr2
&& AND lógico expr1 && expr2
|| OR lógico expr1 || expr2

.7 Operador lógico OR (||).

expr1 == true expr1 == false

expr2 == true true true


expr2 == false true false

.8 Operador lógico AND (&&).


expr1 == true expr1 == false
expr2 == true true false
expr2 == false false false

.9 Operadores de asignación.

Operador Significado
= Asignación simple
*=
/=
%=
+= m operador = n ;
−= equivale a
<<= m = m operador n
>>=
&=
^=

Tabla
16.10 Operadores de incremento y decremento.
Operador Significado
++ Incremento posfijo (a++)
−−
Decremento posfijo (a−−)
++
Incremento prefijo (++a)
−−
Decremento prefijo (−−a)

ESTRUCTURAS DE CONTROL
Las sentencias de control de un lenguaje de programación determinan el flujo de ejecución a través
de un programa. Existen tres categorías: Secuencia, Selección y Repetición.
8

Secuencia y sentencias compuestas


Una sentencia compuesta es un grupo de sentencias que se ejecutan en secuencia y se escriben
encerradas entre símbolos tipo llave. Las sentencias se ejecutan en el orden en que aparecen
{
double m = 4.96;
double n = 3.141516;
double z = m * n;
int i = int(z);
i++;
}

Selección y repetición
Las sentencias o estructuras de control no secuenciales se clasifican en sentencias de selección (if-else
y switch) y sentencias de repetición (iterativas o bucles, for, while y do_while).
Las sentencias for, while y do_while implementan la realización de bucles (lazos, loop)
que contienen sentencias que se ejecutan repetidamente.

Sentencia if
Una sentencia if se utiliza para comprobar una condición determinada. La sentencia if tiene dos
for- matos: if e if-else

Sentencia Switch
La sentencia switch se utiliza para seleccionar entre múltiples valores constantes; por ejemplo, crear
un menú en la pantalla que solicite al usuario seleccionar una de cinco elecciones posibles (‘Almorzar’,
‘Desayunar’, ‘Cenar’, ‘Aperitivo’ y ‘Merienda’). La sintaxis de switch es:
switch (expresión entera o selector)
{
case etiqueta1: sentencia(s);
break;
case etiqueta2: sentencia(s);
break;

default: sentencias;
}
Aplicación de switch
switch (operador)
{
case '+': resultado = m + n;
9

suma ++;
break;
case '-': resultado = m – n;
diferencia --;
break;
case '*': resultado = m * n;
producto --;
break;
case '/': resultado = m / n;
cociente --;
break;
default: cout << "respuesta no válida";
}

Sentencia while
Uno de los conceptos más fundamentales en cualquier lenguaje de programación es el de bucle (lazo,
loop). Un bucle es un conjunto de sentencias (puede no tener sentencias, bucle vacío) que se
ejecutan repetidamente hasta que se cumple una determinada condición o bien se alcanza un número
fijo de iteraciones o repeticiones de todas las sentencias. while, do-while y for son las sentencias típicas
de realización de bucles.
El bucle while es un bucle pre-test (pre-condición) donde la condición que debe cumplirse
en el bucle para su continuación se comprueba antes de cada parada (iteración) del bucle.

1. while (condición) 2. while (condición){


sentencias

Sentencia do-while
El bucle do-while es un bucle post-test (post-condición). La condición del bucle se comprueba
después de cada ejecución. Como resultado el bucle do-while se ejecuta al menos una vez.

do do {
sentencia
sentencia
s
while

Sentencia for
Un bucle for es una sentencia iterativa que normalmente se utiliza con una variable que se
incrementa o decrementa
Sintaxis
10

for (inicialización; expresión-prueba; expresion-actualización)


{
sentencias
}

Sentencias break y continue


Dos sentencias se pueden utilizar en los bucles para romper la secuencia normal de los mismos:
break (ya utilizada en la sentencia switch) y continue.
break aborta un bucle inmediatamente (al igual que sucede en la sentencia switch); realiza un
salto incondicional al final del bucle. Se puede utilizar break en cualquiera de los bucles, haciendo
que la ejecución del programa salte a la siguiente sentencia después del bucle. La sentencia
continue se utiliza en los bucles y hace que comience inmediatamente una nueva iteración del
bucle saltando el resto del cuerpo del bucle que viene a continuación.

Estructura de break y continue


El siguiente segmento de programa permite leer una línea de texto con la función cin.get(car).
El bucle repite cada carácter y utiliza break para terminar el bucle si el carácter es un salto de línea

1. while (cin.get (car))


{
sentencias
if (car =='\n') continue salta el resto
continue; del bucle y comienza
sentencias una nueva iteración.

1. while (cin.get (car)){


sentencias
if (car == '\n')
break; break salta el resto del bucle y va a la siguiente sentencia
sentencias
}
sentencia

FUNCIONES
Una función es un grupo de sentencias que realizan una operación o tarea específica. En la resolución
de problemas tanto por métodos estructurados como por métodos orientados a objetos, se recurre a un
proceso de refinamiento sucesivo que implica la descomposición de un problema o proceso, en subpro-
blemas o subprocesos más pequeños y de menor complejidad.
Las funciones se utilizan para capturar y representar los procesos y subprocesos. El programa
principal (main) de C++ es una secuencia de llamadas a funciones que pueden llamar a otras
funciones.
C++ proporciona mecanismos para crear funciones definidas por el usuario, así como
proporcionar una biblioteca estándar de funciones, como la biblioteca estándar stdio.h de ANSI C,
y las específicas de C++, como biblioteca de flujos, stream, iostream, etc.

Funciones de biblioteca
La función sqrt( ) devuelve la raíz cuadrada de un número y pertenece a la biblioteca estándar de
funciones de C/C++. Para poder utilizar una función de biblioteca se debe incluir el archivo de cabecera
cmath (math.h en los compiladores antiguos que siguen ANSI C o los primeros compiladores de
C++). Una vez incluido el archivo de cabecera correspondiente a la biblioteca, se necesita proporcionar
11

el prototipo. Cada función de la biblioteca C++ tiene un prototipo en uno o más archivos de cabecera.
No se debe confundir el prototipo de la función con la definición de la función. El prototipo solo
describe la interfaz de la función.
double sqrt (double);
es decir, describe la información enviada a la función y la información enviada de retorno. La
definición, sin embargo, incluye el código que calcula la raíz cuadrada de un número. C++ separa estas
dos características, prototipo y definición, de las funciones de biblioteca. Los archivos de biblioteca
contienen el código compilado de las funciones mientras que los archivos de cabecera contienen
prototipos.
La práctica usual es situar los prototipos antes de la definición de la función main(); de modo
similar a:
#include <iostream>
#include <cmath> // o bien math.h, en sistemas antiguos
Una vez incluida la directiva correspondiente; ya se puede utilizar sqrt( ). Por ejemplo, la sentencia
x = sqrt(27.04) // devuelve el valor 5.2 y lo
// asigna a x
La sintaxis a emplear es la siguiente: sqrt (27.04) invoca o llama a la función sqrt( ). La expre-
sión sqrt(27.04) se denomina llamada a la función, la función invocada se denomina función llamada
y la función que contiene la llamada de la función se denomina función llamadora.

Definición de una función (función definida por el usuario)


Una función se representa por un nombre y un conjunto de tipos de operandos, denominados
parámetros, que se escriben encerrados entre paréntesis separados por comas.
Las acciones que debe ejecutar la función se especifica en un bloque, conocido como cuerpo de
la función. Cada función tiene un tipo de retorno asociado.
Sintaxis
12

tipo nombre_función (lista_de_argumentos)


{
Sentencias
}

Para poder utilizar una función se debe especificar su prototipo. Para que el compilador pueda com-
pilar una llamada a una función primero debe conocer la declaración de esa función. Las declaraciones
de las funciones normalmente aparecen antes de la función main( ) en un programa, pero también
se pueden situar en archivos de inclusión.

// devuelve el mcd de dos números a y b


int mcd (int a, int b)
{
while (b)
{
int aux = b;
b = a % b;
a = aux;
}
return a
}

Para llamar a una función se utiliza el operador de llamada que es el nombre de la función con una
lista de argumentos, solo los nombres.
// obtener dos valores para
deducir su mcd cout <<
"Introducir dos números:
\n";
int m, n;
cin >> m >> n;
// obtener el mcd
cout << "mcd: " << mcd(m,n) << endl;
Regla
Sintaxis del prototipo de una función: Tipo nombre (lista de argumentos);

Argumentos de la función: paso por valor y por referencia


En C++ los parámetros de una función son llamados por valor o por referencia. La llamada o paso
por valor significa que el valor del argumento, es decir, una copia del objeto que representa el
argumento, se pasa a la función donde se asigna a una nueva variable, pero aunque la función modifique
el valor del parámetro, la modificación no se mantendrá después del retorno de la función. La
declaración de un argumento que se pasa por valor se realiza, simplemente, declarando el tipo de
argumento.

Paso por valor


double cubo (double x)
int main ()
{

double lado = 10;
double volumen = cubo(lado); → paso por valor

}
double cubo(double n)
{
13

return n*n*n;
}

Paso por referencia


El paso por referencia de los argumentos permite a una función llamada acceder a variables de la
función llamadora. C solo podría pasar argumentos por valor. En el paso por referencia la función
puede modificar el valor del parámetro. Un parámetro se declara que se pase por referencia
declarando dicho parámetro como un tipo de referencia.

Ejemplo: Función típica de intercambio de los valores de dos variables utilizada en algoritmos de
ordenación:
void intercambio (int &m, int &n)
{
int aux = m;
m = n;
n = aux;
}

La declaración de la función intercambio es


void intercambio (int&, int&);
En este caso cuando se hace una llamada
intercambio(a,b)
Los valores de a y b, se modifican dado que el valor de a se cambia por el de b y viceversa. En el caso
del paso por valor de la función mcd, los parámetros m y n se intercambiarían en la ejecución de la
función, pero a y b mantendrían sus valores originales después de la llamada a la función.

Sentencia return
La sentencia return termina la función que se está ejecutando actualmente y devuelve el control a
la función que la llamó. Existen dos formatos de la sentencia return.
return;
return expresión;
Una sentencia return sin ningún valor, solo se puede utilizar en una función que tiene un tipo
de retorno void. Las funciones que devuelven void no requieren contener una sentencia return,
aunque cuando una función utiliza return es para producir una terminación prematura de la función.
El segundo formato de la sentencia return proporciona el resultado de la función. Cada retorno
de una función con un tipo distinto de void debe devolver un valor. El valor devuelto debe tener el
mismo tipo que el tipo de retorno de la función, o debe tener un tipo que pueda ser convertido
implícitamente a este tipo.
Ejemplo: Calcular el importe total de un conjunto de artículos de un supermercado, cada precio ha
de ser incrementado con las tasas de impuestos (IVA).
double precio_total (int numero, double precio)
{
const double IVA =
0.16; // 16% de impuesto double subtotal;
subtotal = precio * numero;
return (subtotal + subtotal * IVA);
}

Sentencia using y el espacio de nombres std


La línea usign namespace std indica al compilador que ponga todos los nombres del espacio de
nombres predefinido std disponibles al programa. Un espacio de nombres es una colección de
nombres o identificadores que se definen juntos. Un programa que contiene esta línea podrá acceder
14

a todas las funciones e identificadores declarados en la biblioteca estándar.


Sin el uso de la directiva using se pueden referenciar los nombres declarados en un espacio de nom-
bres especificando el espacio de nombres real antes de cada uso de un nombre de ese espacio de
nombres. Por ejemplo, se puede utilizar std::cout para referenciar el nombre cout.

Directiva #include

La directiva #include tiene uno de los dos formatos:


1. #include <cabecera> 2. #include "nombre-archivo"

El formato
#include <cabecera>

Se reserva para incluir definiciones que están en la biblioteca estándar y el formato


#include "nombre-archivo"

Se utiliza para incluir un archivo de inclusión definido por el usuario.

CLASES Y OBJETOS
Las clases son un nuevo tipo de dato cuyas variables serán objetos. Una clase es un tipo de dato que
contiene código (funciones) y datos y permite encapsular todo el código y los datos necesarios para
gestionar un tipo específico de un elemento de programa, como una ventana en la pantalla, un
dispositivo conectado a una computadora, una figura de un programa de dibujo o una tarea realizada por
una computadora.

¿Qué son objetos?


Un objeto como “cualquier cosa, real o abstracta, en la que se almacenan datos y aquellos métodos
(operaciones) que manipulan los datos”. Para realizar esa actividad se añaden a cada objeto de la clase
los propios datos asociados con sus propias funciones miembro que pertenecen a la clase. Cualquier
programa orientado a objetos puede manejar muchos objetos
Un mensaje es una instrucción que se envía a un objeto y que cuando se recibe ejecuta sus
acciones; incluye un identificador que contiene la acción que ha de ejecutar el objeto junto con los
datos que necesita el objeto para realizar su trabajo. Los mensajes, por consiguiente, forman una
ventana del objeto al mundo exterior. El usuario de un objeto se comunica con el objeto mediante su
interfaz, un conjunto de operaciones definidas por la clase del objeto de modo que sean todas visibles
al programa. Una interfaz se puede considerar como una vista simplificada de un objeto

¿Qué son clases?


En términos prácticos, una clase es un tipo definido por el usuario. Las clases son los bloques de
construcción fundamentales de los programas orientados a objetos. Booch denomina a una clase
como “un conjunto de objetos que comparten una estructura y comportamiento comunes”.
Una clase contiene la especificación de los datos que describen un objeto junto con la descripción de
las acciones que un objeto conoce cómo ha de ejecutar. Estas acciones se conocen como servicios,
métodos o funciones miembro. El término función miembro se utiliza, específicamente, en C++. Una
clase incluye también todos los datos necesarios para describir los objetos creados a partir de la clase.
Estos datos se conocen como atributos o variables. El término atributo se utiliza en análisis y diseño
orientado a objetos y el término variable se suele usar en programas orientados a objetos.

Una clase es un medio para traducir la abstracción de un tipo definido por el usuario. Combina la
representación de los datos miembros (atributos) y las funciones miembro (métodos) que manipulan
esos datos en una única entidad o paquete que se trata como tal. La colocación de datos y funciones
juntas en una sola entidad (clase) es una idea central en programación orientada a objetos.
15

Definición de una clase


La primera operación que se debe realizar con una clase es definirla. La definición o especificación
tiene dos partes:
• Declaración de la clase. Describe el componente datos, en términos de miembros dato y la
interfaz pública, en términos de funciones miembro, también denominados métodos.
• Definiciones de métodos de las clases. Describen la implementación de las funciones miembro.

La declaración de una clase utiliza la palabra reservada class, seguida de la lista de


miembros dato y métodos de la clase, encerrados entre llaves.

Sintaxis

class NombreClase // identificador válido


{
declaraciones de datos // atributos
declaraciones de funciones // métodos
}; ←Punto y coma obligatorio

Regla práctica
• Los atributos (datos) son variables simples (de tipo entero, estructuras, arrays, float, etc.).
• Los métodos (funciones) son funciones simples que actúan sobre los atributos (datos).
• La omisión del punto y coma detrás de la llave de cierre es un error frecuente, difícil de detectar.

Tabla 17.1 Secciones pública y privada de una clase.

Sección Comentario

public (público)* Se permite el acceso desde el exterior del objeto de la clase


(visible desde el exterior)
private (privado)** Se permite el acceso solo desde el interior del objeto (oculto al
exterior)
* A los miembros públicos se puede acceder desde cualquier objeto de la clase.
** A los miembros privados solo se puede acceder desde métodos de la propia clase.

La sintaxis completa de una clase es:


class NombreClase
{
public:
Sección pública // declaración de miembros públicos
private:
Sección privada // declaración de miembros privado
16

};

No accesible desde el exterior de


Datos o
la clase

Datos o
Accesible desde el exterior de la clase

Declaración de una clase Semaforo


class Semaforo
{
public:
Void cambiarColor ( );
//...
private:
enum Color{VERDE, ROJO, AMBAR};
Color c;
};

En la clase Semaforo se observa que la sección pública declara la definición de los servicios (acción
de cambio de color del semáforo) y en la sección privada, en último lugar, los detalles internos del
semáforo (diferentes tipos de colores del semáforo).

Reglas prácticas en la declaración de una clase


1. Las declaraciones (cabeceras de las funciones) de los métodos, normalmente, se colocan en la
sección pública y las declaraciones de los datos (atributos), normalmente, se sitúan en la sección
privada.
2. Es indiferente colocar primero la sección pública o la sección privada; pero la situación más
usual es colocar la sección pública primero para resaltar las operaciones que forman parte de la
interfaz pública del usuario.
3. Las palabras clave public y private seguidas de dos puntos, señalan el comienzo de las
respectivas secciones públicas y privadas; aunque no se suele utilizar, una clase puede tener varias
secciones pública y privada.
4. Recuerde poner el punto y coma después de la llave de cierre de la declaración de la clase.
¿Control de acceso a los miembros: público o privado?
Los miembros de una clase se pueden declarar públicos o privados. Para ello, el cuerpo de una clase
con- tiene dos palabras clave reservadas: private y public; tanto los datos como las funciones
miembro se pueden declarar en una u otra sección.

Diversas clases con diferentes secciones

class DemoUNo class DiaDelAnio


{ {
private public:
float precio; void leer ( ) ;
char nombre [20] ; void escribir ( ) ;
public; int mes;
int calanclar (int) int día;
… };
};

Las funciones son públicas y los datos privados


17

Definición típica de una clase

CONSTRUCTORES
Un constructor es una función miembro de propósito específico que se ejecuta automáticamente
cuando se crea un objeto de una clase. Un constructor sirve para inicializar los miembros dato de una
clase.
Un constructor tiene el mismo nombre que la propia clase. Cuando se define un constructor no
se puede especificar un valor de retorno, ni incluso void (un constructor nunca devuelve un valor).
Un constructor puede, sin embargo, tomar cualquier número de parámetros (cero o más).
• El constructor tiene el mismo nombre que la clase.
• Puede tener cero, o más parámetros.
• No devuelve ningún valor
La clase Rectangulo tiene un constructor con cuatro parámetros
class Rectangulo
{
private:
int izdo;
int superior;
int dcha;
int inferior;
// constructor
Rectangulo (int i, int s, int d, int inf);
// definiciones de otras funciones miembro
};
18

Cuando se define un objeto se pasan los valores de los parámetros al constructor utilizando una sintaxis
similar a una llamada normal de la función:
Rectangulo Rect (25, 25, 75, 85);

Esta definición crea una instancia del objeto Rectangulo e invoca al constructor de la clase pasando
los parámetros con valores especificados.

DESTRUCTORES
En una clase se puede definir también una función miembro especial conocida como destructor, que
se llama automáticamente siempre que se destruye un objeto de la clase. El nombre del destructor es
el mismo que el nombre de la clase, precedida con el carácter ~. Al igual que un constructor, un
destructor se debe definir sin ningún tipo de retorno (ni incluso void); al contrario que un constructor,
no puede aceptar parámetros. Solo puede existir un destructor.

class Demo
{
private:
int datos;
public:
~Demo( ){datos = 0;} // constructor
~Demo ( ) { } // destructor
};

Los destructores no tienen valor de retorno y tampoco tienen argumentos. El uso más frecuente de un
destructor es liberar memoria que fue asignada por el constructor. Si un destructor no se declara
explícitamente, C++ crea uno vacío de manera automática.

HERENCIA
La herencia es la propiedad que permite definir nuevas clases usando como base clases ya existentes.
La nueva clase (clase derivada) hereda los atributos y comporta- miento que son específicos de ella.
La herencia es una herramienta poderosa que proporciona un marco adecuado para producir software
fiable, comprensible, de bajo costo, adaptable y reutilizable.
La herencia o relación es-un es la relación que existe entre dos clases, en la que una clase denominada
derivada se crea a partir de otra ya existente, denominada clase base. Este concepto nace de la
necesidad de construir una nueva clase y existe una clase que representa un concepto más general; en
este caso la nueva clase puede heredar de la clase ya existente. Así por ejemplo, si existe una clase
Figura y se desea crear una clase Triángulo, esta clase Triángulo puede derivarse de Figura ya
que tendrá en común con ella un estado y un comportamiento, aunque luego tendrá sus características
propias. Triángulo es-un tipo de Figura. Otro ejemplo puede ser Programador, que es-un tipo de
Empleado.

La declaración de derivación de clases debe incluir el nombre de la clase base de la que se deriva y el
especificador de acceso que indica el tipo de herencia (pública, privada y protegida). La primera línea
de cada declaración debe incluir el formato siguiente:
class nombre _clase : tipo_herencia nombre_clase_base
19

En general, se debe incluir la palabra reservada public en la primera línea de la declaración


de la clase derivada; representa herencia pública. Esta palabra reservada consigue que todos
los miembros que son públicos en la clase base permanezcan públicos en la clase derivada

1. class Programador : public Empleado {


public:
// miembros públicos
private:
// miembros privados
};
2. class Triangulo : public Figura
{
public:
// sección pública
...
private:
// sección privada
...
};

Declaración de una clase derivada

• Especificador de acceso public significa que los miembros públicos de la clase base son
miembros públicos de la clase derivada.
• Herencia pública es aquella en que el especificador de acceso es public (público).
• Herencia privada es aquella en que el especificador de acceso es private (privado).
• Herencia protegida es aquella en que el especificador de acceso es protected (protegido).
El especificador de acceso que declara el tipo de herencia es opcional (public, private o protec-
ted); si se omite el especificador de acceso, se considera por defecto private. La clase base
(ClaseBase) es el nombre de la clase de la que se deriva la nueva clase. La lista de miembros consta de
datos y funciones miembro:
class nombre_clase : especificador_acceso opcional ClaseBase {
lista_de_miembros;
};

Tipos de herencia
En una clase existen secciones públicas, privadas y protegidas. Los elementos públicos son accesibles
a todas las funciones; los elementos privados son accesibles solo a los miembros de la clase en que
están definidos; se puede acceder a los elementos protegidos por clases derivadas debido a la propiedad
de la herencia. En correspondencia con lo anterior, existen tres tipos de herencia: pública, privada y
protegida. Normalmente, el tipo de herencia más utilizada es la herencia pública que es
20

predeterminada.
Si accidentalmente se olvida la palabra reservada public, los elementos de la clase base serán
inaccesibles. El tipo de herencia es, por consiguiente, una de las primeras cosas que se debe verificar,
si un compilador devuelve un mensaje de error que indique que las variables o funciones son
inaccesibles.
Herencia pública
En general, herencia pública significa que una clase derivada tiene acceso a los elementos públicos
y protegidos de su clase base. Los elementos públicos se heredan como elementos públicos; los
elementos protegidos permanecen protegidos.
class ClaseDerivada : public ClaseBase {
public:
//sección pública
private:
//sección privada
};

Herencia privada
La herencia privada significa que un usuario de la clase derivada no tiene acceso a ninguno de sus
ele- mentos de la clase base. El formato es:
class ClaseDerivada : private ClaseBase {
public:
// sección pública
protected:
// sección protegida
private:
// sección privada
};
Con herencia privada, los miembros públicos y protegidos de la clase base se vuelven miembros pri-
vados de la clase derivada. En efecto, los usuarios de la clase derivada no tienen acceso a las facilidades
proporcionadas por la clase base. Los miembros privados de la clase base son inaccesibles a las
funciones miembro de la clase derivada.

Herencia protegida
Con herencia protegida, los miembros públicos y protegidos de la clase base se convierten en miembros
protegidos de la clase derivada y los miembros privados de la clase base se vuelven inaccesibles. La
herencia protegida es apropiada cuando las facilidades o aptitudes de la clase base son útiles en la
implementación de la clase derivada, pero no son parte de la interfaz que el usuario de la clase utiliza.
La herencia protegida es todavía menos frecuente que la herencia privada.
Declarar una clase base (Base) y tres clases derivadas de ella D1, D2, D3
class Base {
public:
int i1;
protected:
int i2;
private:
int i3;
};
class D1 : private Base {
void f( );
};
class D2 : protected Base {
void g( );
};
class D3: public Base {
void h( );
21

};

Sintaxis del constructor


La sintaxis de un constructor de una clase derivada es:

Sintaxis de la implementación de una función miembro


La sintaxis para la definición de la implementación de las funciones miembro de una clase derivada
es idéntica a la sintaxis de la definición de la implementación de una clase base.

Herencia múltiple
Herencia múltiple es un tipo de herencia en la que una clase hereda el estado
(estructura) y el comporta- miento de más de una clase base. En otras palabras,
hay herencia múltiple cuando una clase hereda de más de una clase; es decir,
existen múltiples clases base (ascendientes o padres) para la clase derivada
(descendiente o hija).

Ejemplos de herencia múltiple

Sintaxis de la herencia múltiple

class Cderivada : [virtual] [tipo_acceso] Base1,


[virtual] [tipo_acceso] Base2,
22

[virtual] [tipo_acceso] Basen {


public:
// sección pública
private:
// sección privada
...
};

CDerivada Nombre de la clase derivada


tipo_acceso public, private o protected, con las mismas reglas que
la herencia simple
Base 1, Base2,.. Clases base con nombres diferentes
virtual… virtual es opcional y especifica una clase base compatible

class Estudiante {
...
};
class Trabajador {
...
};
class Estudiante_Trabajador : public Estudiante, public Trabajador {

};

POLIMORFISMO
En POO, el polimorfismo permite que diferentes objetos respondan de modo distinto al mismo
mensaje; adquiere su máxima potencia cuando se utiliza en unión de herencia. Por ejemplo, si
figura es una clase base de la que cada figura geométrica hereda características comunes,
C++ permite que cada clase utilice una función (método) Copiar como nombre de una fun-
ción miembro

class figura {
tipoenum tenum; // tipoenum es un tipo enumerado
public:
virtual void Copiar( );
virtual void Dibujar( );
virtual double Area( );
};

class circulo : public figura {


...
public:
void Copiar( );
void Dibujar( );
double Area( );
};
class rectangulo : public figura {
...
public:
void Copiar( ); // el polimorfismo permite que objetos diferentes
// tengan idénticos nombres de funciones miembro
void Dibujar( );
double Area( );
};

Otro ejemplo se puede apreciar en la jerarquía de clases:


23

class Poligono { // superclase


public:
float Perimetro( );
virtual float Area( );
virtual boolean PuntoInterior( );
protected:
void Visualizar( );
};

class Rectangulo : public Poligono{


public:
virtual float Area( );
virtual boolean PuntoInterior( );
void fijarRectangulo( );
private:
float Alto;
float Bajo;
float Izquierdo;
float Derecho;
};

También podría gustarte