Академический Документы
Профессиональный Документы
Культура Документы
C++ estndar
Apuntes de Informtica Industrial y Comunicaciones.
______________________________________________
Steve Jobs.
Presentacin
LaasignaturadeinformticaIndustrialycomunicacionessecomponededospartes
algo diferenciadas como el propio nombre de la asignatura indica. Por un lado se pretende
que el estudiante de esta asignatura comience a programar segn una filosofa de
programacin orientada a objetos (POO), para lo cual se ha escogido el paradigma de este
tipo de lenguajes que es C++. Por otro, se pretende informar y formar al estudiante en la
programacin especfica de sistemas de comunicacin, para lo cual es necesario introducir
coneptosrelativosalossistemasdistribuidosylasredes.
Porltimo,cualquiererratadetectadaporellectorosugerenciaconstructivaquese
considere oportuna agradecera que me fuera transmitida por correo electrnico a
miguel.hernando@upm.es.
Prof.MiguelHernando
4 PROGRAMACIN C++ Y COMUNICACIONES.
PRESENTACIN .......................................................................................................... 2
NDICE DE CONTENIDOS............................................................................................ 5
1. INTRODUCCIN A C++ ..................................................................................... 13
1.1. HISTORIA DE C++ ......................................................................................... 18
Funciones sobrecargadas................................................................................... 50
El destructor ........................................................................................................ 90
4. LA HERENCIA.................................................................................................. 121
4.1. DEFINICIN DE HERENCIA ............................................................................ 122
Sistemas Operativos para pequeos dispositivos: CE, Mobile yPhone ........... 297
EL CLIENTE...................................................................................................... 350
Sinembargo,paralograrestosresultadosesnecesariounesfuerzodelprogramador
en las fases anteriores a la escritura del programa propiamente dicho. Si as no fuera, los
resultados pueden ser francamente decepcionantes. As, para no llevar a engao, y con la
ideadeameneizarligeramenteunosapuntesquedeporsiprometenserdensos,seincluyea
continuacin una entrevista ficticia que durante un tiempo circulo por los foros de
programacin:
Entrevista al padre del C++
El 1 de Enero de 1998, Bjarne Stroustrup, padre del lenguaje C++, dio una entrevista a la revista
de informtica del IEEE. Naturalmente, los editores pensaron que estaba dando una visin
retrospectiva de los siete aos de diseo orientado a objetos, usando el lenguaje que el mismo haba
creado.
Int: Bien, hace unos pocos aos que cambio el mundo del diseo de software, como se siente
mirando atrs?
BS: En este momento estaba pensando en aquella poca, justo antes de que llegase. La
recuerdas? Todo el mundo escriba en C y el problema era que eran demasiado buenos... Las
Universidades eran demasiado buenas ensendolo tambin. Se estaban graduando programadores
competentes a una velocidad de vrtigo. Esa era la causa del problema.
Int: Problema?
BS: Bien, al principio, esos tipos eran como semidioses. Sus salarios eran altos, y eran tratados
como la realeza...
BS: Exacto. Pero, que paso? IBM se canso de ello, e invirti millones en entrenar a
programadores, hasta el punto que podas comprar una docena por medio dlar...
Int: Eso es por lo que me fui. Los salarios bajaron en un ao hasta el punto de que el trabajo de
periodista esta mejor pagado.
BS: Bien, un da, mientras estaba sentado en la oficina, pensaba en este pequeo esquema, que
podra inclinar la balanza un poquito. Pens 'Que ocurrira si existiese un lenguaje tan complicado,
tan difcil de aprender, que nadie fuese capaz de inundar el mercado de programadores?' Empec
cogiendo varias ideas del X10, ya sabes, X windows. Es una autentica pesadilla de sistemas
grficos, que solo se ejecutaba en aquellas cosas Sun 3/60... tena todos los ingredientes que yo
buscaba. Una sintaxis ridculamente compleja, funciones oscuras y estructuras pseudo-OO. Incluso
ahora nadie escribe en cdigo nativo para las X-Windows. Motif es el nico camino a seguir si
quieres mantener la cordura.
BS: Ni un pelo. De hecho, existe otro problema... Unix esta escrito en C, Lo que significa que un
programador en C puede convertirse fcilmente en un programador de sistemas. Recuerdas el
dinero que un programador de sistemas sola conseguir?
BS: Ok, por lo tanto, este nuevo lenguaje tena que divorciarse por s mismo de Unix, ocultando
las llamadas al sistema. Esto podra permitir a tipos que solo conocan el DOS ganarse la vida
decentemente...
BS: Bueno, ha llovido mucho desde entonces. Ahora creo que la mayora de la gente se habr
figurado que C++ es una perdida de tiempo, pero debo decir que han tardado ms en darse cuenta
de lo que pensaba.
BS: Se supona que tena que ser una broma, nunca pens que la gente se tomase el libro en
serio. Cualquiera con dos dedos de frente puede ver que la programacin orientada a objetos es anti
intuitiva, ilgica e ineficiente...
Int: Qu?!?!
BS: Y como el cdigo reutilizable... cuando has odo de una compaa que reutilice su cdigo?
BS: Entonces estas de acuerdo. Recuerda, algunos lo intentaron al principio. Haba esa
compaa de Oregon, creo que se llamaba Mentor Graphics, que revent intentando reescribir todo
en C++ en el 90 o 91. Lo siento realmente por ellos, pero pens que los dems aprenderan de sus
errores.
BS: Ni lo ms mnimo. El problema es que la mayora de las empresas se callaron sus mayores
disparates, y explicar 30 millones de dlares de perdidas a los accionistas podra haber sido dificil...
Dmosles el reconocimiento que merecen, finalmente consiguieron hacer que funcionase
BS: Casi. El ejecutable era tan gigantesco que tardaba unos cinco minutos en cargar en una
estacin de trabajo de HP con 128 MB de RAM. Iba tan rpido como un triciclo. Cre que sera un
escollo insalvable pero nadie se preocupo. SUN y HP estaban demasiado alegres de vender
enormes y poderosas maquinas con gigantescos recursos para ejecutar programas triviales. Ya
sabes, cuando hicimos nuestro primer compilador de C++, en AT&T, compile el clasico 'Hello World',
y no me poda creer el tamao del ejecutable. 2.1 MB.
Int: Qu ?!?!. Bueno, los compiladores han mejorado mucho desde entonces...
BS: Lo han hecho? Intntalo en la ltima versin de C++, la diferencia no ser mayor que medio
mega. Adems existen multitud de ejemplos actuales en todo el mundo. British Telecom tuvo un
desastre mayor en sus manos, pero, afortunadamente, se deshicieron de ello y comenzaron de
nuevo. Tuvieron ms suerte que Australian Telecom. Ahora he odo que Siemens est construyendo
un dinosaurio y se empiezan a preocupar porque los recursos hardware no hacen ms que crecer
para hacer funcionar ejecutables tpicos. No es una delicia la herencia mltiple?
BS: Realmente crees eso ?!?!?! Te has sentado alguna vez y te has puesto a trabajar en un
proyecto C++? Esto es lo que sucede: Primero he puesto las suficientes trampas para asegurarme
de que solo los proyectos ms triviales funcionen a la primera. Coge la sobrecarga de operadores. Al
final del proyecto casi todos los mdulos lo tienen, normalmente los programadores sienten que
deberan hacerlo as porque es como les ensearon en sus cursos de aprendizaje. El mismo
operador entonces significa cosas diferentes en cada modulo. Intenta poner unos cuantos juntos,
cuando tengas unos cientos de mdulos. Y para la ocultacin de datos. Dios, a veces no puedo parar
de rerme cuando oigo los problemas que algunas empresas han tenido al hacer a sus mdulos
comunicarse entre s. Creo que el trmino 'sinergetico' fue especialmente creado para retorcer un
cuchillo en las costillas del director de proyecto...
Int: Tengo que decir que me siento bastante pasmado por todo esto. Dice que consigui subir el
salario de los programadores? Eso es inmoral.
BS: No del todo. Cada uno tiene su opcin. Yo no esperaba que la cosa se me fuese tanto de las
manos. De cualquier forma acert. C++ se esta muriendo ahora, pero los programadores todava
conservan sus sueldos altos. Especialmente esos pobres diablos que tienen que mantener toda esta
majadera. Comprendes que es imposible mantener un gran modulo en C++ si no lo has escrito tu
mismo?
Int: Como?
BS: Recuerdas cuanto tiempo se perda buscando a tientas en las cabeceras sola para darse
cuenta de que 'RoofRaised' era un numero de doble precisin? Bien, imagina el tiempo que te
puedes tirar para encontrar todos los typedefs implcitos en todas las clases en un gran proyecto.
BS: Te acuerdas de la duracin media de un proyecto en C?. Unos 6 meses. No mucho para
que un tipo con una mujer e hijos pueda conseguir un nivel de vida decente. Coge el mismo
proyecto, realzalo en C++ y que obtienes? Te lo dir. Uno o dos aos. No es grandioso? Mucha ms
seguridad laboral solo por un error de juicio. Y una cosa ms. Las universidades no han estado
enseando C desde hace mucho tiempo, lo que produce un descenso del nmero de buenos
programadores en C. Especialmente de los que saben acerca de la programacin en sistemas Unix.
Cuantos tipos sabran que hacer con un 'malloc', cuando han estado usando 'new' durante estos
aos y nunca se han preocupado de de chequear el cdigo de retorno?. De hecho la mayora de los
programadores en C++ pasan de los codigos que les devuelven las funciones. Que paso con el '-1'?
Al menos sabas que tenas un error, sin enredarte con 'throw', 'catch', 'try'...
BS: Lo hace? Te has fijado en la diferencia entre un proyecto en C y el mismo en C++? La etapa
en la que se desarrolla un plan en un proyecto en C++ es tres veces superior. Precisamente para
asegurarse de que todo lo que deba heredarse, lo hace, lo que no, no. Y aun as sigue dando fallos.
Quien ha odo hablar de la prdida de memoria en un programa en C? Ahora se ha creado una
autentica industria especializada en encontrarlas. Muchas empresas se rinden y sacan el producto,
sabiendo que pierde como un colador, simplemente para reducir el gasto de buscar todas esas fugas
de memoria.
BS: Lo dudo. Como dije, C++ esta en su fase descendente ahora y ninguna compaa en su
sano juicio comenzara un proyecto en C++ sin una prueba piloto. Eso debera convencerles de que
es un camino al desastre. Si no lo hace, entonces se merecen todo lo que les pase. Ya sabes?, yo
intente convencer a Dennis Ritchie a reescribir Unix en C++...
BS: Afortunadamente tiene un buen sentido del humor. Creo que tanto l cmo Brian se
figuraban lo que estaba haciendo en aquellos das, y nunca empezaron el proyecto. Me dijo que me
ayudara a escribir una versin en C++ de DOS, si estaba interesado...
Int: Lo estaba?
BS: De hecho ya he escrito DOS en C++, te pasare una demo cuando pueda. Lo tengo
ejecutndose en una Sparc 20 en la sala de ordenadores. Va como un cohete en 4 CPUs, y solo
ocupa 70 megas de disco...
BS: Ahora estas bromeando. No has visto Windows '95? Creo que es mi mayor xito. Casi
acaba con la partida antes de que estuviese preparado
Int: Ya sabes, la idea de Unix++ me ha hecho pensar. Quizs haya alguien ah fuera
intentndolo.
BS: Pero es la historia del siglo. Solo quiero ser recordado por mis compaeros programadores,
por lo que he hecho por ellos. Sabes cuanto puede conseguir un programador de C++ hoy da?
18 PROGRAMACIN C++ Y COMUNICACIONES.
Int: Lo ultimo que o fue algo como unos $70 - $80 la hora para uno realmente bueno...
BS: Lo ves? Y se los gana a pulso. Seguir la pista de todo lo que he puesto en C++ no es fcil.
Y como dije anteriormente, todo programador en C++ se siente impulsado por alguna promesa
mistica a usar todos los elementos del lenguaje en cada proyecto. Eso ciertamente me molesta a
veces, aunque sirva a mi propsito original. Casi me ha acabado gustando el lenguaje tras todo este
tiempo.
BS: Lo odiaba. Parece extrao, no estas de acuerdo? Pero cuando los beneficios del libro
empezaron a llegar... bien, te haces una idea...
Int: Solo un minuto. Que hay de las referencias?. Debe admitir que mejoro los punteros de C...
BS: Hmm... Siempre me he preguntado por eso. Originalmente cre que lo haba hecho.
Entonces, un da estaba discutiendo esto con un tipo que escribe en C++ desde el principio. Dijo que
no poda recordar cuales de sus variables estaban o no referenciadas, por lo que siempre usaba
punteros. Dijo que el pequeo asterisco se lo recordaba.
Int: Bien, llegados a este punto suelo decir 'muchas gracias' pero hoy no parece muy adecuado.
BS: Promteme que publicaras esto. Mi conciencia esta dando lo mejor de mi mismo en estos
momentos.
BS: Quien se lo creera de todas formas?... De todos modos, puedes enviarme una copia de
la cinta?.
Sorprendido?.Nodejadesermsqueunadelasgraciasquecirculanporlaredde
cuando en cuando. Sin embargo, si que hay algo de verdad en la entrevista por lo que se
animaaquealfinalizarelcursoellectorvuelvaaleerlaparaquepuedacomprendermejorlos
riesgos de una programacin orientada a objetos mal entendida, o de las posibles
consecuenciasqueelmalusodelaspotentesherramientasdeC++puedengenerar.
Coneltiempoylaexperienciaellenguajefueevolucionandoparadotarlodemayor
eficiencia desde el punto de vista del programador. En 1980 se aaden al lenguaje C
caractersticascomolasclasescomoresultadodelaevolucindelasestructuras,chequeodel
tipo de los argumentos de una funcin y su conversin si es posible etc, dando como
resultadoloqueenesemomentosellamCconclases1.SuautorfueBjarneStroustrup,ya
mencionadoenlaintroduccin,ysedesarrollenlaAT&TBellLaboratories.
En 1983 este lenguaje fue rediseado y comenz a utilizarse fuera de ATT. Se
introdujeron las funciones virtuales, la sobrecarga de funciones y operadores. Tras
refinamientosymodificacionesmenores,estenuevolenguajeaparecidocumentadoylisto
parasuusobajoelnombredeC++.
Posteriormente C++ ha sido ampliamente revisado lo que ha dado lugar a aadir
nuevas caractersticas como la herencia mltiple, las funciones miembro static y const,
miembrosprotected,tiposdedatosgenricosoplantillas,ylamanipulacindeexcepciones.
Se revisaron aspectos de la sobrecarga y manejo de memoria, se incremento la
compatibilidadconC,etc.ElxitoalcanzadoporellenguajefuearrolladorporloquelaATT
sevienlanecesidaddepromoversuestandarizacininternacional.En1989seconvocel
comitdelaANSI2quemstardeentraformarpartedelaestandarizacinISO.Eltrabajo
conjuntodeestoscomitspermitipublicaren1998elestandarISOC++(ISO/IEC14882)de
forma que el lenguaje pas a ser estable y el cdigo generado utilizable por distintos
compiladoresyendistintasplataformas.
1
Del nombre ingls C with classes.
2
American Nacional Standards Institute.
3
En su traduccin al castellano del trmino library, la palabra ms correcta es biblioteca. Sin
embargo la mayora de los programadores la han traducido por librera, por lo que en estos
apuntes se adoptar esta ltima.
20 PROGRAMACIN C++ Y COMUNICACIONES.
al nombre del lenguaje. De esta forma, al estndar resultante de la norma ISO/IEC 14882
publicadaen1998,seledenominacomoC++98.
Posteriormente existe una nueva especificacin denominada como C++03, como
consecuencia de la aprobacin de la revisin INCITS/ISO/IEC 148822003. En esta, no se
modificalasintaxisyaspectodellenguajeperosiseespecificanaspectosnecesariosparael
desarrollodecompiladores,ylibrerasparaelestndar.
En donde si se produce una variacin del lenguaje que los compiladores han
comenzado a integrar es en el estndar C++11. Aprobado y publicado en Agosto de 2011
como el nuevo estndar. En este caso si que se incluyen variaciones importantes en el
lenguaje,peroconservandocasiprcticamentelacompatibilidadtotalconelestndarC++98.
Lostresndicesquemsseutilizanparamedirlapopularidad deunlenguajeenla
actualidad son el TIOBE Programming Community Index, el Languaje Popularity Index, y el
PYPL,esteltimosoportadoporelanlisisrealizadoporGoogleTrends.
En el siguiente grfico se incluye una captura del ndice TIOBE con fecha Enero de
2015.Estendiceestpensadoparadecidirquelenguajedebesaberunprogramadorafecha
actual, y se calcula no por el nmero de lneas de cdigo sino ms bien por el nmero de
programadores y estudiantes de programacin que en la actualidad siguen, programan o
aprendenunlenguaje.
EsimportantedestacarqueObjectiveCesunlenguajeanlogoaC++peropensado
paradesarrollaraplicacionesparadispositivosmvileseimpulsadoporApplecomomediode
programacindesusdispositivos.Sinembargoestamismaempresacomienzaapromocionar
Swiftcomolenguajebsicoycomoconsecuencia,alestartanligadoaunaplataforma,trasun
fuerteboomentornoa2012,latendenciaahoraesalabajafrenteaC++.Encualquiercasoel
mundodeC,C++,C#yObjectiveCconstituyencasiel40%delndice.Siaesoaadimosque
Lasiguientegrficamuestralatendenciaqueestoslenguajeshanseguidosegneste
ndicedurantelosltimos10aos:
22 PROGRAMACIN C++ Y COMUNICACIONES.
De forma anloga se puede observar un grfico que refleja la popularidad de los
lenguajessegnelLanguajePopularityIndexcombinandoelnmeroderepositoriospblicos,
discusiones, nmero de bsquedas etc. Unos ndices detallados se pueden ver en
http://langpop.com.Elresumenqueserealizaendichapginavieneaconfirmarlomismo:
EstosdatosdiscrepanligeramenteconelmostradoporPYPL.Encualquiercaso,de
nuevo,eltroC,C++,C#juntoconJavasonpredominantes.LadiferenciaentreTIOBEyPYPL
bsicamentesedebeaqueTIOBEcuentaelnmerodepaginaswebquehablandellenguaje
(simplificando mucho) mientras que PYPL se centra en el nmero de visitas y bsquedas
arrojadasporGoogleTrends.UncasocuriosoeseldeObjectiveCquetieneunos20millones
pginasenlawebfrentealos11millonesdeC,sinembargolaslecturasybsquedasdeCson
actualmente30vecesmsenCqueenObjectiveC.
Siesciertoquedurantelaltimapoca,sehaobservadouncrecimientoconstantey
aceptacin de Python como lenguaje de programacin pero an es pronto para saber si
realmente es un lenguaje consolidado, particularmente por el hecho de que vara un
excesivamenteentreversinyversinydequeancarecedeunaespecificacinestndar.Se
observa que es un lenguaje muy usado para el prototipado rpido y para trabajar como
sustitucin de java por su caracterstica multiplataforma y la facilidad de utilizacin de
funcionalidadesexternas.DeigualformaseobservaunimportantecrecimientodeJavaScript,
24 PROGRAMACIN C++ Y COMUNICACIONES.
Finalmente, para dar por cerrada la introduccin se reflejan algunos trminos
comnmente adoptados, pero que facilitarn la estructura de la exposicin. La parte de C
incluida en C++ es conocida como C y puede compilarse en C++ sin ningn problema. La
sintaxis y las reglas de edicin en general son iguales, por lo que a las modificaciones
introducidasporC++alaedicindecdigoprocedural(esdecir,comosisetratasedeC)se
lasdenominamodificacionesmenoresyaquesonfcilmenteasumiblesporunprogramador
deC.
Alasmodificacionesintroducidasparasoportarlaprogramacinorientadaaobjetos
ylaprogramacingenrica,selasdenominamodificacionesmayores,puestoquerequieren
parasuusodeuncambioradicalenlafilosofadeprogramacin.
C++:AC++comoveremosseloconsideraunlenguajeintermedioconcaractersticas
de Orientacin a Objetos. De hecho, como se ver, la razn de ser del lenguaje es
impulsar C al paradigma de la programacin orientada a objetos. Muchisimo
software est construido en C++, en general todos los que requieran de una alta
eficiencia. Se usa bsicamente para software de sistemas, de aplicaciones,
videojuegosyaplicacionestantodeservidorescomodeclientesenparticularlasque
requierandealtapotencia.
C#: (csharp) es un lenguaje desarrollado por Microsoft que intenta combinar los
principiosdeC,C++yJava,yseusabsicamenteeneldesarrollodeprogramaspara
Windows. Su mayor inconveniente es precisamente el constituir un lenguaje
asociadounaplataforma.
Pythonesunlenguajedealtonivel,interpretado,enprincipiopensadoparatrabajar
enlapartedelservidordelossitiosweboenaplicacionesdemviles.Seleconsidera
un lenguaje sencillo para principiantes debido a su facil lectura y su sintaxis
compacta,detalformaqueenmuypocaslineassepuedenhacermuchascosasque
en otros de los lenguajes anteriores conllevaran mucho ms cdigo. Actualmente
destaca su uso en las webs y aplicaciones de Instagram, Pinterest, Biicode, y hay
desarrolladounpotenteyconocidoentornodedesarrollowebDjango.Esutilizado
porGoogle,YahooylaNasacomopartedesucdigo.
JavaScript.Esunlenguajeinterpretadotantoparaelclientecomoparaelservidor,
desarrolladopor Netscapeyque deriva mucha de su sintaxis de C.En contrade lo
que indica el nombre, no es Java y su desarrollo es paralelo. Puede usarse al igual
queesteultimoparamultiplesplataformaspormediodelintrpretedelnavegador,
yseconsideraesencialparaeldesarrollodelapartemsinteractivayautnomade
lasfuncionesweb.Ultimamentehasufridounfuerteincrementodadoquepermite
por la potencia de los navegadores el desarrollo de juegos que por su naturaleza
funcionan tanto en ordenadores de escritorio como en dispositivos mviles. Est
embebidoenChrome,enSafari,yenlosintrpretesdeAdobe
Esimportantedestacarquelaaparicindeestemododeprogramacinnoresponde
a un diseo de laboratorio en el que un conjunto de cabezas pensantes se han dedicado a
disear el lenguaje de programacin perfecto, sino que proviene de la extraccin de los
modosdeprogramarquepocoapocosefueronestableciendoentrelosprogramadoresde
los lenguajes estructurados para lograr sistemas ms eficientes y robustos. Es decir, la
mayoradelosmecanismosquesevanapresentarrespondenanecesidadesespecficasdela
programacinprctica.
Antesdeprocederadescribiralgunosdelostrminosbsicosutilizadosencualquier
lenguajedeprogramacinconfilosofadePOOsevaaintroducirunpocolaideadeenque
consiste.
Enloslenguajesestrictamenteprocedurales(C,PASCAL,BASIC)comoseindicaensu
propiadescripcin,elelementoprincipalloconstituyeelalgoritmooprocedimiento.Esdecir,
dealgunamanera,losdatossonunelementoexternoalprogramaylafuncinprincipalde
este es manejarlos. As de forma natural se tiende hacia un sistema centralizado en donde
existe un motor principal dividido en distintos elementos, denominados funciones, que se
encargan de ir manejando ymodificandouna seriededatos que van pasando de unlado a
otro.
Aspodramospensarenunalibreraendondelosdatoscorrespondenaloslibros,y
elencargadodeordenarlosforrarlos,destruirlos,etc.esellibrerocontodossusayudantes.Es
claro que ni el local, ni las estanteras, ni los libros y hojas son responsables de decidir en
dondehandesituarsenideculessuprecioetc.apesardequesonloscontenedoresdela
informacin que determina estas caractersticas. Ser el librero el que al observarlo y
examinarlodecidirsuubicacin,clasificacin,precio,elforro,etc.
28 PROGRAMACIN C++ Y COMUNICACIONES.
Objetos.Unobjetoesunaentidadquetieneunosatributosparticulares(datos)
y unas formas de operar sobre ellos (los mtodos o funciones miembro). Es
decir,unobjetoincluye,porunaparteunaseriedeoperacionesquedefinensu
comportamiento, y una serie de variables manipuladas por esas funciones que
definen su estado. Por ejemplo, una ventana Windows contendr operaciones
comomaximizaryvariablescomoanchoyaltodelaventana.
Mtodos.Unmtodoesunafuncinimplementadadentrodeunobjetoconla
finalidadderealizarunaseriedeoperacionessobrelosdatosquecontiene.As,
en el ejemplo anterior, las ventanas de Windows tienen el mtodo maximizar,
minimizar,cerrar,etc.quemodificanelaspectodelaventanaaldibujarse.
Abstraccin.EselmecanismodediseoenlaPOO.Nospermiteextraerdeun
conjuntodeentidadesdatosycomportamientoscomunesparaalmacenarlosen
clases. El ejemplo clsico para entender estas caractersticas se realiza con los
vehculos.Fcilmentesepuedeestablecerunadefinicindevehculocomotodo
aquello que es capaz de transportar personas. En este caso tendremos que
aviones,coches,barcos,triciclosybicicletastienenalgoencomnquedebemos
poderrepresentarenunsistemadeprogramacinorientadoaobjetos.
procedimientosespecialesdeconstruccinydestruccindeobjetos.Enconcreto,cadaclase
tienedosfuncionesmiembroespecialesdenominadasconstructorydestructor.
Constructor:Funcinmiembroqueesautomticamenteinvocadacadavezque
se define un objeto, su objetivo es la inicializacin del mismo. Toma el mismo
nombre que la clase, puede recibir parmetros y podemos tener varios
constructoresdefinidos.
EnprimerlugarsededicaruncaptuloaintroducirlasmodificacionesmenoresdeC
que aparecen en C++. Es decir, algunas de las caractersticas que utilizables en una
programacin procedural aporta C++. Seguidamente se dedicar el resto de captulos a ir
explicando ordenadamente los distintos mecanismos que tiene C++ para realizar una
programacin orientada a objetos. Para ello se comenzar explicando en ms detalle el
concepto de clase y de objetos. Una vez establecida la base de lo que es una clase, se
dedicar un captulo a explicar el mecanismo de la herencia tan importante para lograr un
cdigoeficienteyreutilizable.Esteconceptosecompletarconeldesarrollodelpolimorfismo
en C++ que se aborda en el quinto captulo, especialmente interesante si se observa las
consecuenciasqueestetienesobreWindows.UnodelosaspectosmsdesconocidosenC++
(para los programadores nveles) se aborda en el captulo 6 al introducir el concepto de
plantilla.
HastaestepuntolosconceptosdesarrolladossoncomunesaloslenguajesdePOO.
En el captulo siete se proceder a exponer el modo en que C++ realiza las operaciones de
entrada y salida, as como algunos de los objetos y funciones bsicas disponibles en las
libreras estandar con esta finalidad. Para finalizar la parte de los apuntes dedicada a la
exposicindellenguajeC++serealizarunabrevedescripcindelmecanismoparatratarlos
errores:lasexcepciones.
32 PROGRAMACIN C++ Y COMUNICACIONES.
Alolargodelcontenidodeestecursoseirnintercalandoejemplosyaplicacionesde
los conceptos explicados que permitirn a su vez ilustrar aspectos auxiliares de C++. Un
elementoimportanteyquerequerirunaexposicindetalladaenunaasignaturaposterior,
eslarepresentacingrficadeloselementosqueintegranunsistemainformtico.Porellose
hanidointegrandodeformanaturalestosmodesderepresentargrficamenteloselementos
yseincluyeunbreveresumendelosmismosenelcaptulo8.
En C++ los ficheros de cdigo se terminan con la extensin cpp de forma que el
entornodedesarrollopuededecidirquecompiladorvaautilizar.
Punctuators:sonloscaracteresespecialesqueseutilizancomoseparadores
delasdistintasconstruccionesdeunlenguajedeprogramacin:#[]{};:*
=()
Keywords:quesonpalabrasreservadasquesolosepuedenutilizarparalo
queestprevistoporellenguajesalvoqueseanpartedeunliteral(cadena
decaracteres).
Identificators:sonpalabrasqueutilizaremosparadenominaralgodentro
delcdigo,comoporejemploelnombredeunavariable.Losidentificadores
enCyC++sonsensiblesamaysculasyminsculas4,debencomenzarpor
unaletradelalfabetoinglsoelcarcter_,yacontinuacinsepodrn
agregarletrasynmeros,incluyendolabarrabajahastaunmximode31
enANSIC.Obviamentenopodrnsernuncaigualesaunapalabra
reservada.
Literals:Sedenominaasalaespecificacindeunvalorconcretodeuntipo
dedato.
o Numeros:33.14160.314e10.314e+1.3141elf
Mediantesufijospodemosmodificareltipobsicoqueesintpara
lasconstantessinpunto,ydoubleparalasquetienen(Fparafloat)
(Lparalong)(Uparaunsigned).
Medianteprefijospodemosexpresarunmododecodificacin(0x
hexadecimal)(0paraoctal)
o Caracteres:a0\n\\\
o Cadenasdecaracteres.Lascadenasdecaracteresestn
constituidasporunvectodecaracteresexplcitosmsuncarcter
terminadorqueesel\0quecorrespondealvalor0.HolaMundo
\HolaMundoentrecomillas\
4
Case sensitive
Operators:Igualqueenmatemticassoncombinacionesdesmbolosoun
smboloquerealizanunaaccinespecficasobreunoomsoperandosy
quehabitualmentedevuelvenunvalor:+*/%>>etc.
Decaraalaescrituradecdigosesuelenseguirunasrefcomendacionesenelusode
identificadores.Seexponenaqubrevementeantesdepasaraverlasnuevaspalabrasclavey
operadoresintroducidosenC++:
o MACROS y DEFINICIONES: todo en maysculas. Si tienen varias palabras
separarlascon_
#define RADIO 3.0F
#define MAX_NUM 3453
o Estructuras y tipos de datos definidos por el usuario: se recomienda
empezarlos con mayscula y poner en mayscula el comienzo de cada
palabraexplicativa
struct PoligonoRegular { } ;
o Funcionesymtodos:comenzarsuidentificadorconunverboenminscula
habitualmente en infinitivo o imperativo, a continuacin cada palabra en
mayscula
void imprimeContenido( )
o Variables:todoenminsculas.Sihayvariaspalabrasseparalaspor_.
int contador = 0, cuenta_cuentos = 0;
Operador Significado
:: Operadorderesolucindembitodeunavariableofuncinmiembrodeuna
clase.Denominadocomooperadorscope.
this Tomaelvalordeladireccindelelementodesdeelquehasidoinvocado.
& Adicionalmente a los significados en C, se utilizar para definir referencias y
alias.
new Crea un objeto del tipo indicado a continuacin. Modo habitual de reserva
dinmicadememoriaenC++
delete Destruyeunobjetocreadodinmicamenteconeloperadornew
.* Accede al miembro de una clase cuando el miembro es referenciado por un
puntero.
->* Accedealmiembrodeunaclasecuandotantoelmiembrocomolainstanciade
laclaseestnreferenciadosporunpuntero.
typeid Identificacindetipo
???_cast Conversionesforzadasdeltipodeunaexpresin.
Losdosmodosdeaccesonuevos(.*y>*),noaparecernmsenestosapuntespor
loqueseincluyeacontinuacinunbreveejemployexplicacindelosmismos.
#include <cstdio>
struct Complex{
float real;
float imag;
};
void main()
{
struct Complex a={0,0}, *b; //creo dos variables de tipo Complex
float Complex::*valor; //defino un puntero a floats de Complex
b=&a;
//le asigno a valor la direccion relativa de la parte real
valor= &Complex::real;
a.*valor=5.0F;
printf("\n%f + %fj",a.real, a.imag);
//le asigno a valor la direccion relativa de la parte imag
valor = &Complex::imag;
b->*valor=3.0F;
printf("\n%f + %fj",a.real, a.imag);
}
Cuandodosoperadorestienenlamismaasociatividad(porejemploporquefueranel
mismo) entonces se sigue la regla de asociatividad, que es de izquierda a derecha o de
derecha a izquierda: 3+5+24+8 lo interpretaremos como (((3+5)+2)4)+8 es decir de
izquieraaderecha.
1 ::
2 () [] . -> v++ v-- ??? cast
>>
typeid
3 -a +a ~ ! & * ++v v sizeof new
<<
delete (tipo)
4 ->* .* >>
5 a*b a/b a%b >>
6 a+b a-b >>
7 << >> >>
8 < <= > >= >>
9 == != >>
10 a&b >>
11 a^b >>
12 a|b >>
13 && >>
14 || >>
15 a?b:c <<
16 = *= /= %= += -= <<= >>= &= |=
<<
^=
17 , >>
Lasnicasexcepcionessonparaeloperadorternario,yenlosoperadoreslgicos&&
y||(siendoelordendeizquierdaaderecha).Todoestetemaesunpocomscomplejodado
queademshayqueanalizarsilosefectosdelaexpresinseevalanantesodespus,pero
paraelpuntoenelquenosencontramosessuficienteconestasnociones.
2.4. Comentarios
En el C original, la inclusin de comentarios en los ficheros de cdigo vena
delimitado por una combinacin de caracteres de comienzo (/*) y otra de finalizacin de
comentario(*/).Detalformaquetodoeltextocontenidoentreestosdosdelimitadoresera
eliminado por el preprocesador antes de proceder a realizar cualquier operacin de
interpretacin.
Tenga en cuenta que los bool y los int son tipos distintos. Sin embargo, cuando es
necesario, el compilador realiza una conversin automtica de forma que pueden utilizarse
librementevaloresbool(trueyfalse)juntoconvaloresintsinutilizarunaconversinexplcita.
int x = 0, y = 5;
if (x == false) printf("x falso.\n"); // Ok.
if (y == true) printf("y cierto.\n"); // Ok.
if ((bool) x == false) printf("x falso.\n"); // cast innecesario
Estasconversionesentretiposlgicosynumricos,sonsimplementeunaconcesin
delC++parapoderaprovecharlagrancantidaddecdigoCexistente.TradicionalmenteenC
sehacacorresponderfalsoconelvalorceroyciertoconelvaloruno(odistintodecero).
Paraconvertirtiposaritmticos(enumeraciones,punterosopunterosamiembrosde
clases)auntipobool,lareglaesquecualquiervalorcero;punteronulo,opunteroamiembro
de clase nulo, se convierte a false. Cualquier otro valor se convierte a true. En principio el
estndar establece que solo los valores enteros son convertidos automticamente siendo
necesariounaconversinexplcitaenotrocaso,sinembargo,amenudo,loscompiladoresno
requierendeestecastporcomodidad.
void main()
{
/*peticin de variables*/
int j;
struct complejo micomplejo;
/*cdigo*/
j=sizeof(struct complejo);
}
ElmismocdigoenC++quedara:
//declaracin del patrn de la estructura complejo
struct complejo
{
float x;
float y;
};
void main()
{
//peticin de variables
int j;
complejo micomplejo;
//cdigo
j=sizeof(complejo);
}
Seobservacomodesdeelpuntodevistadelcdigo,quedamsclaroycmodo.
Por otro lado, al igual que ocurra con las estructuras y las uniones, en las
enumeracionessesimplificalaindicacindeltipodurantesuusoprescindiendodelapalabra
enum.
ElsiguienteextractodecdigomuestraunejemplodeunaenumeracinenC++:
enum notas {suspenso, aprobado, bien, notable, sobresaliente};
notas nota1 = bien;
notas nota2;
nota2 = notas(2); //conversin explcita.
// nota2 = 2; sera en C pero que en C++ es incorrecto
Sin embargo, si es posible realizar la asignacin contraria. Es decir, una variable
entera puede recibir el valor de una variable de tipo enumeracin. Por defecto, el nmero
42 PROGRAMACIN C++ Y COMUNICACIONES.
entero asignado a cada uno de los posibles valores de una variable enum van por orden
comenzandodesde0.Deestaforma,suspensovale0,aprobadovale1,bienvale2,etc.Sin
embargo,elprogramadorpuedeestablecerestosvaloresenladefinicindelaenumeracin.
Elsiguientecdigomuestraestasdoscaractersticas:
enum colores {rojo=3,verde=5, azul, amarillo=8};
int i = verde;
Enestecaso,rojovale3,verdevale5,azulvale6yamarillovale8.Esdecir,cuando
explcitamentenosedaunvalor,sesiguelanumeracindelvaloranterior.
Paraayudaraentenderelniveldefuerzaqueestetipodedatostiene,lassiguientes
propiedadessecumplenalahoradeevaluarexpresionescontiposenum:
Nohabrerrorsiaunavariabledetipoenumleasigno(indicandolaconversin)un
valornodefinido:nota2=notas(100)seraunaexpresinvlida.
Uniones annimas
Aunque su aplicacin ms inmediata se da en el interior de estructuras ms
complejas,esconvenientemencionaryaqueC++admiteladefinicindeunionesannimas.
Sufinalidadesladedefinirunconjuntodecampos(miembrosenelcasodeclases)ubicados
en la misma zona de memoria. Simplifica el acceso a estos campos evitando el tener que
utilizar, como ocurre en C, el indicador del tipo de acceso sobre la unin. Para visualizar la
variacin,semostrarelmismosegmentodeprogramaescritoenCyenC++:
ElsiguienteprogramaenC:
struct datos /*definicin del patrn de estructuras*/
{
int tipo;
union _dato /*union dentro de la estructura*/
{
char caracter;
int entero;
float decimal;
}dato;
};
int main()
{
struct datos midato;
midato.tipo=2;
midato.dato.entero=5;
}
EstemismocdigoescritoenC++quedaracomosigue:
struct datos /*definicin del patrn de estructuras*/
{
int tipo;
union /*union dentro de la estructura*/
{
char caracter;
int entero;
float decimal;
};
};
int main()
{
datos midato;
midato.tipo=2;
midato.entero=5;
}
Estoincluyelaposibilidaddedeclararvariablesenelinteriordeunasentenciacomo
semostrarenlosejemplossiguientes:
void funcion(void)
{
int i=8;
44 PROGRAMACIN C++ Y COMUNICACIONES.
for(int j=0;j<i;j++)
{
printf(Hola mundo);
int k=3;
printf(valor de k %d,k);
}
if(--i==0)return;
}
EnCquedabaclarocualeraelmbitodeunavariable,puestoqueunavariablelocal
eravisibledesdetodoelcuerpodelafuncinenlaqueestabadefinida,yunavariableglobal
loeradesdeelpuntoenelqueestabaenelcdigoenadelante.
En C++, el mbito de una variable es desde el punto en el que esta est declarada
hastaelfinaldelbloqueenelqueseencuentra.
UnavariablelocalocultaaligualqueenCaunavariablemsglobalrelativamente.
Es decir, bajo un mismo nombre, las variable que se considerar ser la ms local
entrelasvisibles.
C++ dispone del operador (::), llamado operador de resolucin de visibilidad. Este
operador,antepuestoalnombredeunavariableglobalqueestocultaporunavariablelocal
delmismonombre,permiteaccederalvalordelavariableglobal.Noesposible,sinembargo,
acceder a una variable local que est oculta por otra variable local. El siguiente ejemplo
muestraelmododeusodeeloperadorscope.
int i=0;
void main()
{
int i;
while(::i<10)
{
++::i;
for(i=0;i<10;i++)
printf(%d : %d\n,::i,i);
}
return 1;
}
Enesteprogramaseharealizadolaanidacindedosbuclescondositeradoresdel
mismonombre,unoglobalyotrolocal.
Portimo,laduracindelasvariableslocales(auto)serelbloqueenelqueestn
definidas.Esdecir,quelavariableesdestruidaenelmomentoenquesefinalizalaejecucin
delbloqueenelqueseencuentrasudeclaracin.Esposibledefinirvariablesestticasaligual
que en C, de forma que una variable local definida como esttica (static) no es destruida
hastaelfinaldelprograma,yportantosloescreadalaprimeravezqueseejecutaelbloque
enelqueseencuentrasudeclaracin.
}
}
Elcompiladorarrojalossiguienteserrores:
1. Lainicializacindeiesevitadaporlasetiquetascase.
2. Lainicializacindeiesevitadaporlasetiquetadefault.
3. Redefinicindei.
La forma ms sencilla de evitar este error sin modificar el nmero de variables
localesdelprograma,esestablecerenelinteriordecadacasounbloque:
int main()
{
int i=2;
float v;
switch (i)
{
case 3:
{int i=5;}
break;
case 2:
{
v=3.5F;
for(int i=0;i<10;i++)v=1.0F;
}
default:
v=3.0F;
break;
}
}
5
Este apartado ha sido extraido y reformateado de la siguiente pgina web:
http://c.conclase.net/curso/index.php. Los cursos de C y C++ con clase son altamente
recomendados por lo bien que estn explicados y el carcter docente de esta pgina
web.
Almacenamiento automtico: Por defecto las variables locales son auto. Estas
variablessecreandurantelaejecucin,yseeligeeltipodememoriaautilizarenfuncindel
mbitotemporaldelavariable.Unavezcumplidoelmbito,lavariableesdestruida.Esdecir,
unavariableautomticalocaldeunafuncinsecrearcuandoseadeclarada,ysedestruiral
terminarlafuncin.Unavariablelocalautomticadeunbucleserdestruidacuandoelbucle
termine.
Almacenamientoesttico:Elespecificadorstaticseutilizatantoparavariablescomo
parafunciones:
static <tipo> <nombre_variable>;
static <tipo> <nombre_de_funcin>(<lista_parmetros>);
Cuandoseusaenlapeticindeunavariable,esteespecificadorhacequeseasigne
una direccin de memoria fija para el objeto mientras el programa se est ejecutando. Es
decir,suduracinesladelprograma.Encuantolavisibilidadconservaelquelecorresponde
segnelpuntodelcdigoenqueaparezcaladeclaracin.Debidoaquetieneunaposicinde
memoriafija,suvalorpermanece,aunquesetratedeunavariabledeclaradadeformalocal,
entre distintas reentradas en el mbito del objeto. Los objetos estticos no inicializados
tomanpordefectounvalornulo,aunqueconvienesiempreindicarelinicializadorcombuena
practicaalahoradeprogramar.
Estainicializacinsloafectaralmomentodecreacindelavariable.
Curiosamentesiutilizamoselmodificadorstaticsobreunavariableglobal(fuerade
cualquier bloque) estaremos indicando que esa variable no debe ser accesible desde otros
ficherosdelprograma,sinosolodesdeelficheroquelasestdeclarando.
Almacenamientoexterno:paraindicarlosehaceusodelapalabraclaveexternyes
aplicabletantoavariablescomoafunciones:
extern <tipo> <nombre_variable>;
[extern] <tipo> <nombre_de_funcin>(<lista_parmetros>);
Esteespecificadorseusaparaindicarqueelalmacenamientoyvalordeunavariable
oladefinicindeunafuncinestndefinidosenotromdulooficherofuente.Lasfunciones
declaradasconexternsonvisiblesportodoslosficherosfuentedelprograma,salvoquese
definalafuncincomostatic.
Elespecificadorexternslopuedeusarseconobjetosyfuncionesglobales.
48 PROGRAMACIN C++ Y COMUNICACIONES.
Lasdeclaracionesdeprototipossondeclaracionesexternaspordefecto,deahqueal
igualqueocurraconlaespecificacinauto,normalmentenoveamosestapalabraclaveenlas
declaraciones de funciones. Se puede usar extern "c" con el fin de prevenir que algn
nombre de funcin escrita en C pueda ser ocultado por funciones de programas C++. Este
especificador no se refiere al tipo de almacenamiento, ya que sabemos que en el caso de
prototiposdefuncioneseselespecificadorpordefecto.Enrealidadesunadirectivaqueest
destinadaalenlazador,yleinstruyeparaquehagaunenlazado"C",distintodelqueseusa
parafuncionesenC++.
Lgicamente,esteespecificadorlousaremosconprogramasqueusenvariosficheros
fuente,queserlomsnormalconaplicacionesquenoseanejemplosoaplicacionessimples.
Almacenamientoenregistro:Paraespecificarestetipodealmacenamientoseusael
especificadorregister.
register <tipo> <nombre_variable>;
Indicaalcompiladorunapreferenciaparaquelavariablesealmaceneenunregistro
delaCPU,siesposible,conelfindeoptimizarsuacceso,consiguiendounamayorvelocidad
deejecucin.Losdatosdeclaradosconelespecificadorregistertienenelmismombitoque
las automticas. De hecho, slo se puede usar este especificador con parmetros y con
objetoslocales.
Funciones inline
C++permiteintroducirelmodificadorinlineenladeclaracindelasfunciones.Con
este modificador indicamos al compilador que consideramos conveniente que las llamadas
realizadas a esta funcin sean sustituidas por el cuerpo de cdigo de la funcin. El efecto
respecto de la funcionalidad del programa es el mismo en ambos casos, pero en caso de
realizarse esta sustitucin, el programa resultante es ms rpido, al evitarse el salto a la
funcin,acostadeuncdigoejecutablemsextenso.
Es recomendable utilizar el modificador inline en funciones pequeas, que son
llamadasenpocoslugares(queesdiferenteaqueseanllamadaspocasveces).
Para poder asignar el modificador inline a una funcin, dicha funcin debe estar
definidaantesdequeseainvocada,delocontrarioelcompiladornolotendrencuenta.Por
este motivo, las funciones inline son normalmente definidas en los ficheros de cabecera.
Modificar una funcin para que sea de este tipo implica anteponer inline al tipo del valor
retornadoporlafuncin.
inline int maximo(int a, int b)
{
return((a>b)?a:b);
}
int main()
{
int a,b;
scanf(%d%d,&a,&b);
printf(El mximo de %d y %d es %d,a,b,maximo(a,b));
}
ElcomportamientodelasfuncionesinlinerecuerdaalasmacrosdeC.Sinembargo
las macros de C definidas por medio de la directiva al preprocesador #define, pueden
fcilmente llevar a errores de cdigo debido a que se realiza una sustitucin textual de los
parmetros. Esto queda perfectamente resuelto con esta nueva herramienta aportada por
C++.
Por ejemplo, en C, la macro correspondiente a la funcin anterior, se escribira
correctamentedelaformasiguiente:
#define MAXIMO(a,b) (((a)>(b))?(a):(b))
Enelsiguientecdigo,seobservaunefectonodeseadoenelvalordelasvariables
paraelcasodeusodelasmacros:
void main()
{
int a=2,b=4,max;
50 PROGRAMACIN C++ Y COMUNICACIONES.
max=MAXIMO(++a,--b);
printf(el mximo de %d y %d es %d,a,b,max);
}
Elmensajedesalidadelejemplosera:
Elmximode3y2es2
Esto es debido a que a ha sido incrementada una vez y b dos veces, una en la
evaluacin de la expresin de la condicin, y otra en la evaluacin de la expresin del
resultado.Estetipodeerrores,ascomolasprecaucionesclsicastomadaspormediodelos
parntesisquedansolventadaspormediodelusodelasfuncionesinline.
As,enelficherodecabecerasepodraincluirlasiguientelnea,siendoentoncesla
funcinmximoconsideradacomoinline:
//cabecera.h
class MiClase
{
int maximo(int a,int b){return((a>b)?a:b);};
};
A diferencia de lo habitual, el modificador inline se asocia con la definicin de la
funcinenvezdeconsudeclaracin.Enelfondoestoesporqueunafuncindefinidacomo
inlinenoserutilizadaenlafasedeenlazadoyportantopodremostenerdistintasversiones
deunafuncinenlasdistintasunidadesdecompilacin.
Funciones sobrecargadas
LasobrecargadefuncionesesunacaractersticadeC++quehacequelosprogramas
seanmslegibles.
Consiste en declarar y definir varias funciones distintas que tienen un mismo
nombre. En el momento de la compilacin se decide si se llama a una u otra funcin
dependiendodelnmeroy/otipodelosargumentosactualesdelallamadaalafuncin.
Lasobrecargadefuncionesnoadmitefuncionesquedifieransloeneltipodelvalor
deretorno,peroconelmismonmeroytipodeargumentos.
Elsiguienteejemplomuestracomosobrecargarlafuncinsumaparanmerosreales
ynmeroscomplejos:
struct complejo
{
float real, imaginario;
}
float suma(float a, float b)
{
return (a+b);
}
complejo suma(complejo a, complejo b)
{
complejo c;
c.real=a.real+b.real;
c.imaginario=a.imaginario+b.imaginario;
return c;
}
void main()
{
complejo a={1.0F,1.5F},b={0.0F,1.1F},c;
float d=3.0F,e=8.2F,f;
c=suma(a,b); //utiliza la funcion suma de complejos
f=suma(d,e); //utiliza la funcion suma de enteros
}
Enelusodelasobrecargadefuncioneshayquetenercuidadoconlaposibilidadde
queseproduzcanambigedadesenladecisindequfuncinvaaserejecutada.
En caso de que pueda darse esta ambigedad por ser los tipos de datos
promocionables o equivalentes se puede romper la ambigedad mediante una conversin
explcita.Porejemplo:
void imprime(double a);
void imprime(long a);
void main()
{
int b=8;
imprime(b);
imprime(static_cast<long>(b));
imprime((double)b);
}
Enesteejemplo,laprimerallamadaalafuncinimprimeesambiguapuestoqueb
puedeserpromocionadotantoadoublecomoalong.Estaambigedadesresueltaenlosdos
casossiguientes.EnlasegundallamadasehautilizadounodelosnuevosoperadoresdeC++
que es la conversin esttica al tipo indicado entre llaves. Este nuevo operador aparece
especialmenteporlaposibilidadderealizarconversionesconverificacindetipodurantela
52 PROGRAMACIN C++ Y COMUNICACIONES.
ejecucinpormediodesudualdynamic_cast.Elmatizentrelosditintostiposdeconversin
severmsadelante,basteahoraconmencionarlos.
Esimportantedestacarqueunavezomitidounargumentoenunallamada,hayque
omitirtodoslosposteriors.Esdecir,noesposibleescogeromitirunparmetrosyotrono,
sloesposibleomitirlosparmetrosdesdeunpuntodeterminado.
Otroaspectointeresanteatenerencuentaparaevitarerroresenlacompilacin,es
queencasodeexistirunprototipodedefinicindelafuncin(bienenelficherodecdigoo
en una cabecera), los parmetros por defecto deben situarse en el prototipo y no en la
definicin.As,elejemploanteriorquedaracomosigue:
void imprimeVector(float v[], int tam=3,bool linea=false);
void main()
{
float vector[5]={1.0F,2.0F,3.0F,4.0F,5.0F};
imprimeVector(vector);
imprimeVector(vector,5);
imprimeVector(vector,5,true);
}
void imprimeVector(float v[], int tam,bool linea)
{
printf(();
for(int i=0;i<tam;i++)printf( %f,v[i]);
if(linea)printf( )\n);
else printf( ) );
}
Unareferenciaesunnombrealternativooaliasparaunavariable.
Antesdecomenzarsinembargocontodaslasposiblesaplicacionesypeculiaridades
de este nuevo tipo de variables, la regla prctica para no terminar lindose es la ya
expuestaantes.Unareferencianoesunpunterooalgoexternoalavariablereferenciadaes
lamismavariableconunnombredistinto.
Severahoralaaplicacinmssencillaperoconmenosutilidad:lacreacindeun
aliasdeunavariable.
Laformadedeclararunareferenciaaunobjetoengenerales:
tipo &alias = variable
Al igual que en los punteros, en caso de tener varias declaraciones seguidas, se
adjuntarel&alidentificadordelareferenciaenvezdealtipobsico.
int a,b;
int &c=a,d,&e=b;
54 PROGRAMACIN C++ Y COMUNICACIONES.
Todareferencia,exceptolasdeclaradascomoparmetrosformalesenunafuncin,
debe ser siempre inicializada. Adems una referencia no puede alterar el objeto al que se
refiereunavezinicializadadeigualformaquenoesposiblemoverunavariabledeunsitioa
otrodelamemoria,sinoqueunavezcreadapermaneceenelmismositio.
Elsiguienteejemplomuestralacreacindeunaliasdeotravariable:
void main()
{
int i;
int& j=i; //j es un alias de i
for(i=0;i<3;i++)printf(%d,j); //imprime 012
for(j=0;j<3;j++)printf(%d,i); //imprime 012
for(j=0;i<3;j++)printf(%d,j); //imprime 012
}
Elefectoeselmismoquesisustituimostodaslasjpori,sonlamismavariable!,y
por tanto los tres bucles for hacen exactamente lo mismo. Se observa por tanto, que la
aplicacindelasreferenciasdentrodeunmismobloquetienepocautilidad.Elhechodeque
sehayamencionadoestaaplicacinesqueayudaalentendimientodelmododeprocederde
lasreferencias.
c=*a;
*a=*b;
*b=c;
}
void main()
{
int x=1,y=2;
printf(contenido de x e y: %d, %d\n,x,y); /*imprime 1, 2 */
permutar(&x,&y); /*llamada a la funcin con la direccin de
las variables x e y*/
printf(contenido de x e y: %d, %d\n,x,y); /*imprime 2, 1 */
}
Aunquedesdeelpuntodevistadelmododefuncionamientorealdelordenador,es
mucho ms correcto el modo en que este cdigo se escribe en C, en C++ las referencias
permiten realizar esta operacin mediante la creacin de alias de los argumentos actuales,
consiguiendodesdeelpuntodevistadelprogramadorunanotacinmuchomscmoda:
void permutar(int &a, int &b)
{
int c;
c=a;
a=b;
b=c;
}
void main()
{
int x=1,y=2;
printf(contenido de x e y: %d, %d\n,x,y); //imprime 1, 2
permutar(x,y); //llamada a la funcin directamente con
//las variables x e y
printf(contenido de x e y: %d, %d\n,x,y); /*imprime 2, 1 */
}
double& componenteX(vector2D& a)
{
return (a.x);
}
void main()
{
vector2D vector={3.0,4.0};
printf(la x normalizada es %d,normaliza(vector).x);
componenteX(vector)=8.0;
...
}
Ntese que gracias a las referencias, ahora es posible utilizar la llamada a una
funcinenelladoizquierdodeunaasignacin.Noasignamosalafuncinelvalorsituadoala
derecha,sinoqueasignamosdichovaloralavariableretornadaporreferenciaporlafuncin,
puesto que la expresin de llamar a la funcin se ha convertido en un alias de la variable
retornada.
Es importante considerar que slo es posible retornar referencias a variables cuya
vida supere a la duracin de la funcin, por el mismo motivo que en C no se retornan
punterosavariablesdeclaradasenelinteriordelafuncin:cuandoseterminalaejecucinde
lafuncin,lasvariablesautodefinidasensuinteriorsondestruidas.
Elsiguientecdigoseraportantoerrneo:
vector2D& normaliza(vector2D a)
{
double modulo;
modulo=sqrt((a.x)*(a.x)+(a.y)*(a.y));
a.x/=modulo;
58 PROGRAMACIN C++ Y COMUNICACIONES.
a.y/=modulo;
return a;
}
void main()
{
vector2D vector={3.0,4.0;
printf(la x normalizada es %d,normaliza(vector).x);
}
Elcompiladorgeneraraelsiguienteerror:
Returningaddressoflocalvariableortemporary
Esto es debido a que los argumentos formales son variables locales de la funcin
inicializadasconelvalordelosargumentosactuales.Comoconsecuencia,lavariablequese
retornaporreferenciaesunavariablelocalcopiadelaintroducidacomoparmetro.
Por ltimo, cabe destacar en el mensaje de error, que se seala que se est
retornando la direccin de una variable local. Hasta este punto se ha evitado mencionar la
relacin existente entre punteros y referencias para evitar confusiones en su uso. Sin
embargo hay que destacar que en el fondo las referencias no son ms que triquiuelas del
compiladorparahacerelcdigomslegible,siendoenverdaddireccionesdelasvariables(es
decirpunteros)loquesepasatantoenlosargumentoscomoenelretorno.
Existenmuchasaplicacionesdirectasenlareservadinmicadememoria,talescomo
la generacin de listas, pilas, rboles, vectores de tamao variable, etc. Simplemente para
ayudar a recordar estas ideas, se expone a continuacin un programa en C que permite
almacenartantosnmerosdistintosdecerocomoquepanenlamemoria(realmente50%de
El operador new.
Eloperadornewessemejantealafuncinmallocaunquecomoseveralolargodel
cursonoselimitaexclusivamentearealizarlareservadememoria.Porahoraseconsiderar
quepermiteasignarmemoriapertenecientealreadealmacenamientolibreparaunobjeto
oparaunamatrizdeobjetosdemomentoentindaseporobjetounavariable.
El ejemplo muestra dos posibles sintaxis para la misma operacin. Ambas son
equivalentes.Esposible,comosehavisto,realizarladeclaracindeunpunteroylareserva
dememoriaenlamismasentencia:
int *a = new int;
Lallamadaaloperadornewdevuelveunpunteroalespaciodememoriareservado,
siendoelpunterodeltipoespecificado.Porestemotivo,adiferenciadelafuncinmallocno
esnecesariorealizarelcast(conversinforzada)alpunteroretornado.Sinohubieraespacio
para la reserva de memoria, el operador devuelve un puntero NULL si no se utilizan las
excepciones(severmsadelante).
Cuando el operador new reserva memoria para una matriz, el tipo de datos que
devuelveesdeltipodeladireccinalprimerelementodelamatriz.Sesueleconsiderarpor
este motivo como un operador distinto, aunque en el fondo es el mismo modo de
funcionamientoqueenlainstruccinmallocdeC.
As,lossiguientesejemplosmuestrancomocrearvectoresymatricesdinmicamente
coneloperadornew:
1 int num=6,i;
2 int *a = new int;
3 int *b = new int[num];
4 int (*c)[3] = new int[8][3];
5 int *d[3];
6 for(i=0;i<3;i++)d[i]=new int[8];
Enesteejemplosehaestablecidolacomparacinentrelareservadememoriapara
un solo objeto o variable (lnea 2), y la reserva de memoria de vectores. En el caso de los
vectoreselmododeprocederesexactamenteigualqueenC.Unvectoralfinalesunpuntero
queapuntaaunazonadememoriaendondecomienzanasituarseloselementosdelvector
deformaordenada.Detalforma,queladireccincorrespondeconladelprimerelementoy
tiene por tanto este tipo. Recordemos, que la razn principal para proceder as, esta en la
aritmticadepunterosyenlossistemasdeindireccin,lograndodeestaformaqueunode
los mecanismos bsicos del lenguaje tenga correspondencia directa con el modo de
funcionamientodeunmicroprocesador.
Obsrvese a su vez como al igual que en C internamente no existen matrices de
elementosdemsdeunadimensin,sinoquetodoseconsideracomovector.Enelcasode
unamatrizdedosdimensionesenCyC++seconsiderancomounvectordevectores.Estoes
loqueaparecereflejadoenlalnea4.Aunquealaderechalapeticinaparececonelaspecto
deunamatrizde8por3,loqueentiendeC(yesoesloquesereflejaalaizquierda)esquese
estsolicitandounvectordevectoresdetresenteros,porloqueladireccinderetornoesla
de vector de tres enteros. Este modo de lectura, ampliamente recomendado, se logra si se
siguen las reglas de asociatividad de los corchetes. El operador new, considera slo los
primeroscorchetes,lodemscorrespondealtipobsicodelvector.
Puestoqueloscorchetestienenpreferenciasobreeloperador*,esnecesarioponer
losparntesis,paraqueelcompiladorentiendaqueclnea4esunpuntero(primeroselee
loquehayentreparntesis)avectoresdetresenteros.
El operador delete
El operador delete destruye un objeto creado por el operador new, liuberando el
sistemaoperativolamemoriaocupadapordichoobjeto.AdiferenciadeloqueocurraenC
conlafuncinfree,deletepuedeserutilizadosobreunpunteronulo(apuntaacero)encuyo
caso no realiza ninguna operacin. Es importante recordar que nunca se puede pedir la
liberacindeunamemoriaquenohasidoreservadadinmicamente.Ocomoreglaprctica,
Eloperadordeletesolopuedeseraplicadoazonasdememoriareservadasmediante
unnew.
Segn lo indicado, las operaciones que hay que realizar para eliminar los objetos
reservadosparaelanteriorejemploson:
1 delete a;
3 delete [] b;
4 delete [] c; //observese que se considera c como vector
5 for(i=0;i<3;i++)delete [] d[i]; //para cada new un delete
Dondeseobservaenlalnea1elmodoenelquedeleteesutilizadoenlaeliminacin
deunsoloobjeto.Yenlaslneassiguientes,elformatoenlallamadaadeleteparaprocedera
laliberacindelamemoriareservadaparadistintosvectoresdeelementos.
mbito,siemprequeindique"Pepe"seharreferenciaimplcitaal"Pepe"dedichombito,
perodesdefuerasiempresepodrdecir"PepeeldeAlmera"o"PepeeldeToledo".
Adems se pude indicar, por medio de la palabra clave using el uso de un mbito
externo por defecto. Esto nos permite subdibidir el espacio globald e nombres en espacios
personalizadosevitandolasredefinicionesoelagotacmientodeidentificadoresenproyectos
grandes.
Por ltimo, es interesante aclarar que puedo aadir elementos a un espacio de
nombresencualquierparte,yenmuchosficherosdistintos.Lohabitualesqueunalibreraen
C++porejemplotengatodossuselementosdefinidosenunnamespaceespecfico.
namespace Almeria{
int Pepe;
void foo(){
Pepe=73;
}
}
namespace Toledo{
int Pepe;
}
void foo(){
Almeria::Pepe=3;
Toledo::Pepe=5;
}
void foo2()
{
using namespace Almeria;
Pepe=8;
Toledo::Pepe=3;
Almeria::foo(); //hay foo() y Almera::foo() es necesario
}
lapantalla(mostrarunmensajeounosvalores)yunflujodeentradapuedeserelconjunto
deteclaspulsadasenunteclado.
Por tanto, un flujo es un objeto que hace de intermedio entre el programa y el
destino u origen de la informacin. En la mayora de los casos no es relevante para el
programa la naturaleza fsica del sistema que enva o recibe los datos, sino que lo que
interesaeselcarctersecuencialdelosdatosenviadosorecibidos.
Dehecho,aligualqueenC,lasoperacionesdeentradaysalida(lecturayescritura)
siguenengeneralsiempreelmismoesquema:inicialmenteseabreelcanaldecomunicacin
oflujo(aperturadeunficheroounpuerto),seenvaorecibeinformacinduranteeltiempo
que sea necesario, y finalmente, cuando ya no es necesario este canal, se cierra para no
sobrecargaralsistemaoperativo.
Sepuedeobjetaraloanteriorqueparaelusodeprintfnohasidonuncanecesario
realizarlaaperturadelcanal.Escierto,peroesqueenC,todaslasoperacionesdeentraday
salida estndar se realizan por medio de ficheros que en algunos casos estn ocultos. Al
comenzarcualquierprogramaenCseproducelaaperturaautomticadetresficheros:stdin,
stdout, y stderr, que constituyen respectivamente la entrada estndar de datos, la salida
estndar y la salida para mensajes de error estndar. De forma que es el sistema el que
realiza la apertura de ficheros por nosotros. Cuando uno escribe una intruccin printf()
realmenteestescribiendofprintf(stdout,).
VolviendoentoncesaC++,elcomportamientoesanlogo,peromuchomscmodo.
Cuando un programa en C++ se ejecuta, se crean automticamente tres flujos identificados
porlossiguientesobjetos:
1. Unflujodeentradaestndar(normalmenteelteclado):cin.
2. Unflujodesalidaestndar(habitualmentelapantalla):cout.
3. Dosflujoshacialasalidaestndardeerror(pantalla):cerr,yclog.
Aunque segn avance el curso, se irn viendo aspectos ms avanzados sobre los
flujos de datos, a continuacin se muestra el modo en que se realizan las operaciones de
entradaysalidaenC++.
Losflujoscinycout.
Enprimerlugar,parapoderutilizarlosflujosanteriormenteexpuestos,esnecesario
incluirlalibreraestndariostream.h.
La gran ventaja o comodidad del uso de flujos, reside en que cada dato sabe
inicialmentecomosedebetransmitir(esdecir,eljuegodecaracteresquelorepresenta),yen
caso de ser un tipo de datos definido por el usuario, es posible indicar como se realiza su
escrituraosulecturagraciasalaposibilidaddesobrecargarlosoperadores>>y<<.
El siguiente ejemplo ilustra como se imprimen una serie de datos por pantalla
medianteelusodelflujoestndarcout.
#include<iostream.h>
int main()
{
int i=2,j=3;
double dato=5.3;
char a=a,b[]=hola;
cout << i;
cout << i << j << endl;
cout << el valor de dato es << dato << endl;
cout << el carcter a= << a << y la cadena b << b << endl;
}
Aligualqueenscanflaseparacinentrecadavalorintroducidoserealizapormedio
deelespacioenblancosegnellenguajeC(espacio,tabulador,cambiodelnea,).
Un aspecto importante que se abordar en el captulo correspondiente es el de la
gestin de errores y el estado de los flujos, as como la especificacin de formatos (por
ejemplo, el nmero de decimales que se utilizarn en la impresin de un double). De
momento se mencionar que son operaciones fcilmente realizables pero que escapan al
enfoquedeestecaptulo.
2.13. EJERCICIOS
EJERCICIO2.1
Dadalasiguienteestructuradedatos:
***********************************/
#define MAX_CADENA 100
EJERCICIO2.2
Disear e implementar una funcin de nombre norma que permita obtener la norma
de un vector de float de dimensin n y que en funcin del parmetro adicional
bnormalizadetipoboolpermitanormalizar(true)ono(false)elvectorentrante.Ademspor
defecto,seconsiderarquelosvectoressondedimensin3yquenosedeseamodificarel
vectorintroducido.
EJERCICIO2.3
Una funcin contiene las siguientes sentencias de C++. Indquese la impresin por pantalla
quedichasinstruccionesprovocan.
int a,b,c=1;
a=3,2+3;
b=(3,2+3);
c+=c+=2;
printf("a=%d b=%d c=%d",a,b,c);
EJERCICIO2.4
Indqueselaimpresinporpantalladelsiguienteprograma:
68 PROGRAMACIN C++ Y COMUNICACIONES.
#include <stdio.h>
void main()
{
int i=0;
for(i=0;i<30;i++){
if(!(i%2)||!(i%3))continue;
printf("%d ", i);
}
}
EJERCICIO2.5
Indquecualdelassiguienteslneasmarcadasconunrectnculoescorrecta(elcompiladorla
acepta):
enum notas {suspenso, aprobado, bien, notable, sobresaliente};
int var;
notas nota1, nota2;
nota1=bien;
nota1=1;
nota1=(notas)1;
nota1=suspenso+1;
nota1=suspenso+aprobado;
var=5+bien;
var=bien+5;
var=notable+bien;
var=nota1+bien;
nota1++;
for(var=suspenso;var<sobresaliente;var++)
printf(%d,var);
for(nota2=suspenso;nota2<sobresaliente;nota2++)
printf(%d,(int)nota2);
EJERCICIO2.6
Indiquelaimpresinporpantalladelcdigosiguiente,silasecuenciadenmerosintroducida
porelusuarioeslasiguiente:12,13,14,15,16,17,18,12,13y14.
#include stdio.h
int j=0;
for(int i=0;i<num;i++)if(vector[i]<vector[j])j=I;
return vector[j];
}
void main(){
int lista[3]={0,0,0};
for(int i=0;i<10;i++)scanf(%d,&menor(lista,3));
printf(Valores: %d %d %d,lista[0],lista[1],lista[2]);
}
3. El Concepto de Clase
Desdeelcomienzodeestosapuntes,sehadestacadolaimportanciadelcambiode
mentalidad o filosofa a la hora de programar que introduce el lenguaje C++. Sin embargo,
hastaestecaptulo,apenasseharealizadoningunavariacinsobreelmododeprogramarde
C.Bien,laparteintroductoriaodesituacinseterminenelcaptuloanterioryportanto,
con elconcepto de clase, objeto y encapsulamiento se comienza a trabajar en la idea de la
ProgramacinOrientadaaObjetos,precisamenteconlaintroduccindelelementobsicoel
objeto.
Como ya sehaba comentado en elcaptulo introductorio un objetoes unaunidad
que engloba en s mismo datos y procedimientos necesarios para el tratamiento de esos
datos.Hastaahorasehanrealizadoprogramasenlosquelosdatosylasfuncionesestaban
perfectamente separados. Cuando se programa con objetos esto no es as, cada objeto
contiene datos y funciones. Y un programa se construye como un conjunto de objetos, o
inclusocomounnicoobjeto.Losobjetosseagrupabanenclases,delamismaformaqueen
la realidad, existiendo muchas mesas distintas (la de mi cuarto, la del comedor, la del
laboratorio,ladelcompaeroolama)agrupamostodosesosobjetosrealesenunconcepto
msabstractodenominadomesa.Detalformaquepodemosdecirqueunobjetoespecfico
esunarealizacinoinstanciadeunadeterminadaclase.
Porejemplo,enlosprogramasdeWindows,cadabotnclsicodeunainterfazesun
objeto.Todoslosbotonesson instancias orealizacionesdelaclaseCButton deWindows.
Luegoloquerealmenteexistesonlosobjetos,mientrasquelasclasessepuedenconsiderar
comopatronesparacrearobjetos.Peroadems,estosbotonespertenecenaunobjetoms
grandequeeseltapizsobreelqueestnpintados.Esteobjetodewindowshabitualmenteno
esmsqueunainstanciadelaclaseCDialogquepermitecrearobjetosquecontienenobjetos
que soncapaces de interaccionar con el usuario de forma grfica.Muchas de las interfaces
queestamosacostumbradosamenejarenwindowssoninstanciasdeestaclasedeobjetos.
Posteriormente,sisequisieratrabajarcmodamenteconestenuevotipodedatos
se definan una serie de funciones pensadas para manipular o extraer informacin de los
mismos.As,seraposibledefinirunafuncinquepermitieraextraerelmdulodecualquier
complejomedianteelsiguientecdigo:
float moduloComplejo(complex a)
{
float m;
m=sqrt(a.real*a.real+a.imag*a.imag);
return m;
}
Se observa que mediante este sistema por un lado estn los datos y por otro las
funciones,aunqueestasfuncionesestndefinidasexclusivamenteparatrabajarconeltipode
datoscomplex.
Las clases en C++ se pueden considerar como la evolucin de las estructuras. Las
clasespermitennosloagruparlosdatoscomoocurreenlasestructurassinoqueadems
nospermitenincluirlasfuncionesqueoperanconestosdatos.
LasclasesenC++tienenlossiguienteselementosoatributos:
Unconjuntodedatosmiembro.Enelcasodeloscomplejos,elnmeroreal
que representa la parte real y el nmero real que representa la parte
imaginaria, sern datos miembro de la clase complex. La informacin
guardadaenestosdatossonloqueharndistintounobjetodeotrodentro
deunamismaclase.Aunquenormalmentesiempretenemosdatosenuna
clase,noesnecesarioqueexistan.
Unosnivelesdeaccesoalosdatosymtodosdelaclase.Supongamosque
sehacreadounaclasequepermitealmacenarunconjuntodenmeros,de
tal forma que es como una especie de saco, en donde se van agregando
nmeros, y despus se pueden ir extrayendo de uno en uno o se puede
preguntarcuantosnmeroshayalmacenados.Enlaclaseexistirnportanto
un conjunto de datos que permitir ir almacenando los nmeros que se
introducen (data)yun datoquenospermite conocer cuntosnmeros se
han introducido hasta ese momento (num). No sera conveniente que en
esta clase, el programador pudiera modificar libremente el valor de num,
puestoqueestevalorindicaelnmerodeobjetosquesehanintroducidoy
nounvalorarbitrario.PorelloenC++sepuedeestablecerquealgunosde
losdatosyfuncionesmiembrodeunaclasenopuedanserutilizadosporel
programador,sinoqueestnprotegidososondatosprivadosdelaclaseya
quesirvenparasufuncionamientointerno,mientrasqueotrossonpblicos
ototalmenteaccesiblesalprogramador.Estacualidadaplicablealosdatos
oalasfuncionesmiembroesloquesedenominacomoniveldeacceso.
Ladeclaracindeunaclaseloconstituyeladescripcindelosdatosyfuncionesque
pertenecenalaclase.Enladeclaracinnoesnecesarioindicarelcdigocorrespondientea
losmtodosdelaclase,sinoquebastaconindicarelnombredelmtodoysusparmetrosde
entradaysalida.ElconceptoesanlogoaldeladeclaracindefuncionesenC,endondelo
queinteresaescomunicaralcompiladorlaexistenciadeunafuncin,elmodoenqueestase
debeusar(argumentosyvalorderetorno),ynoseescribeelcdigo.
Ladefinicindeunaclase,eslaparteopartesdelprogramaquedescribenelcdigo
contenidoenlosmtodosdelaclase.LaideaesanlogaaladefinicindelasfuncionesenC.
Lainstanciacin,eselprocesoporelcualsecreaunobjetodeunaclase.
Estos tres conceptos quedan ilustrados en una primera versin y utilizacin de la
clasecomplexparalosobjetosquerepresentannmeroscomplejos.
74 PROGRAMACIN C++ Y COMUNICACIONES.
//comienzo de la declaracin
class complex
{
private:
double real;
double imag;
public:
void estableceValor(float re,float im) ;
float obtenModulo(void) ;
void imprime() ;
};
//fin de la declaracin
Severcondetalleelsignificadoquetienentodasestasnuevaspalabrasyporquese
usandelaformaenlaquesehanutilizado:
Declaracin de la clase
La sintaxis ms simple de declaracin de una clase es igual que la utilizada para la
declaracindelasestructurasenC,perocambiandolapalabraclavestructporclassyconla
posibilidaddeintroducirfuncionesynivelesdeaccesoentrelasllaves:
class <identificador>
{
[<nivel de acceso a>:]
<lista de miembros de la clase>
[<nivel de acceso b>:
<lista de miembros de la clase>]
[<>]
}[lista de objetos];
La primera lnea establece el nombre con el que vamos a identificar la clase por
mediodelapalabraintroducidaenelcampo<identificador>.Enelejemplo,elidentificadores
lapalabracomplex.
Una vez establecido el nombre se procede a indicar los datos y los mtodos de la
clase.Aunquenoexisteunaespecificacinenelordenenquelosdatosyfuncionesdebenser
declarados, es habitual proceder a introducir en primer lugar los datos miembro con sus
nivelesdeaccesoydespuselconjuntodemtodostantopblicoscomoprivados.
En el ejemplo se indica en primer lugar que los elementos que se van a declarar
posteriormenteserndecarcterprivado.Estodeharealizadopormediodelapalabraclave
private.Deestaforma,losdatosrealeimagdetipodoubleslopodrnsermodificadosy
consultadospormediodemtodosdelaclase.Veremosconmsdetallelautilidaddetodo
estoalhablardelconceptodeencapsulamientoenelsiguienteapartado.
Despus se indica que a partir del punto en el que parece la palabra public se
declaranlasfuncionesydatosmiembrodelaclasequesonaccesiblesdesdefueradelaclase,
y que por tanto constituyen la interfaz. En el ejemplo, tres funciones tienen este nivel de
acceso: estableceValor, obtenModulo e imprime. Con esto se finaliza la declaracin de la
claseporloqueseprocedeadefinirla.
76 PROGRAMACIN C++ Y COMUNICACIONES.
<tipo> <iden_clase>::<iden_metodo>(<argumentos>)
{
[cdigo del mtodo]
}
Seobservaqueyanoesnecesarioindicarsielmtodoespblicooprivado,puesto
queestainformacinsehabaestablecidoyaenladeclaracin.
Tambinhayquedestacarquelosmtodosdeunaclase,accedendirectamentealos
datosymtodosdelapropiaclase,mientrasquedesdefueracomoenelcasodelafuncin
main,esnecesarioutilizareloperador.parapoderejecutarlos.
Elpunteroimplcitothis.
Loquehacedistintoadosobjetosdeunamismaclaseesprecisamentelosdatosque
contienen. Por ello, los datos miembro o atributos de un objeto son distintos para cada
objeto,sinembargolasfuncionesomtodossoncomunesatodoslosobjetosdeunamisma
clase.Esdecir,cadaobjetoalmacenasuspropiosdatos,peroparaaccederyoperarconellos,
todoscompartenlosmismosmtodosdefinidosensuclase.Porlotanto,Paraqueunmtodo
conozcalaidentidaddelobjetoenparticularparaelquehasidoinvocado,C++proporciona
un puntero al objeto denominado this. De hecho, el compilador reescribe el cdigo de los
mtodosquehemosdefinido,anteponiendoantetodoslosidentificadoresdelosatributosla
expresin(this>).Implcitamente,todoslosmtodosnoestticosdeunaclasetienencomo
argumentoimplcitounpunteroalobjetoquellamaalmtodo,yesteesaccesiblepormedio
delapalabrathis.
Porejemplo,lafuncionestableceValorpodrareescribirsedelaformasiguiente:
void complex::estableceValor(float re, float im)
{
this->real=re ;
this->imag=im ;
}
AligualqueocurreenC,paraaccederalosmiembrosdeunaestructuraapartirde
unpunteroaunavariabledeestetipo,seutilizaeloperadorflecha.
Yparaejecutarlosdistintosmtodosquesehandefinido,seutilizaeloperador.
queindicaquesetratardeunmiembrodelobjetoqueloantecede.Atravsdeloperador
punto, slo se podr acceder a los atributos y mtodos pblicos, quedando los elementos
privadosprotegidosporelcompilador.Deestaforma,lasiguienteexpresindaraunerrorde
compilacin:
micomplejo.real=2.0;
Porloqueparaestablecerelvalordelnmerocomplejoslosepuedehacerusodel
mtodoprevistoestableceValorqueobligaaintroducirtantolaparterealcomolaimaginaria.
Todoestotienemuchoqueverconelconceptodeencapsulamientoquesevera
continuacin.
3.3. Encapsulamiento
Ya se ha comentado que para una clase, los nicos elementos accesibles desde el
exterior son aquellos que han sido declarados como pblicos. Por tanto, los miembros
privadosdeunaclasenosonaccesiblesparafuncionesyclasesexterioresadichaclase.
EnlaprogramacinorientadaaObjetos,losnivelesdeaccesosonelmedioquese
utilizaparalograrelencapsulamientoquenoesmsquecadaobjetosecomportedeforma
78 PROGRAMACIN C++ Y COMUNICACIONES.
autnomayloquepaseensuinteriorseainvisibleparaelrestodeobjetos.Cadaobjetoslo
respondeaciertosmensajesyproporcionadeterminadassalidas.
El siguiente ejemplo ilustra como este concepto es muy importante de cara a
obtener uncdigo reutilizable y seguro que es laprincipal finalidad de la POO. La siguiente
clase lista de nmeros, nos permite almacenar un mximo determinado de nmeros en
memoriaesttica.Dichaclase,evitaqueelusuariocometaerroresdeejecucintalescomo
acceder a un nmero que no existe o introducir un conjunto de nmeros que supere la
capacidaddealmacenamientodeestalistaesttica.
Elprecioquehayquepagarporestaproteccineseltenerqueutilizarparatodaslas
operacionesmtodosyportantofunciones,aunqueestasoperacionesseanmuysencillas.Sin
embargo,elresultadoesrobusto,yfcilmentetrasladableavariosprogramas.
class listaNumeros
{
private:
int num;
int lista[100];
public:
int agregarNumero(int val);
int extraerNumero(int ind);
int numeroNumeros(void);
listaNumeros(void);
};
//constructor de la clase en breve se ver su utilidad
listaNumeros::listaNumeros(void){
num=0;
}
int listaNumeros::agregarNumero(int val){
if(num<100)lista[num++]=val;
else return -1;
return num;
}
int listaNumeros::extraerNumero(int ind){
if((ind<num)&&(ind>=0))return lista[ind];
return 0;
}
int listaNumeros::numeroNumeros(){
return num;
}
#include <iostream.h>
void main()
{
listaNumeros milista;
int i,val=1;
while(val!=0)
{
cout<<"introduzca un numero (finalizar con 0):";
cin>>val;
if(val!=0)val=milista.agregarNumero(val);
}
cout<<"\nLa lista de nmeros es la siguiente:\n";
for(i=0;i<milista.numeroNumeros();i++)
cout<<milista.extraerNumero(i)<<" ";
cout<<"\n*********FIN DEL PROGRAMA**********\n";
}
Las funciones diseadas exclusivamente para servir de interfaz de la parte privada
sonhabitualmentepequeas,yocupanmuypoquitaslneas.Dehechoesmuyhabitualque
existanunaseriedemtodoscuyanicafuncinesdevolverelvalordeunatributo,yquepor
tantosolocontienenunasentencia:returndelatributo.
Enestecasoeshabitualescribirelcontenidodeestasfuncionesdirectamenteenla
declaracin de la clase. Cuando un mtodo se define en la declaracin de una clase este
mtodopasaserdetipoinline.Loquesignificaquecuandoseallamadoporcualquierparte
delprograma,envezderealizarelprocesodellamadaaunmtodo,elcompiladorrealizauna
sustitucindelasentenciadellamadaporelcontenidointerpretadodelmtodo.Portanto,
ser un proceso rapidsimo en ser ejecutado, a costa de que el cdigo de la funcin se
repetirtantasvecescomollamadasexplcitasseescribenenelcdigo.
Por ello, aunque cualquier funcin puede ser definida como inline, slo se utiliza
paraaquellasfuncionespequeasenlasqueelprocesodeejecucindeunmtodoesmayor
quelaejecucindelmtodoens.Estoesloqueocurrircontodaslasfuncionesdeconsulta
omodificacindeatributosnopblicosdeunaclase.
Elcdigoanteriorpodraserreescritoentoncesdelasiguienteforma:
class listaNumeros
{
private:
int num;
int lista[100];
public:
int agregarNumero(int val);
int extraerNumero(int ind)
80 PROGRAMACIN C++ Y COMUNICACIONES.
{
if((ind<100)&&(ind>=0))return lista[ind];
return 0;
}
int numeroNumeros(void){return num;};
listaNumeros(void){num=0;};
};
Cuandoelmtodoestanbrevequepuedeserescritoenlamismalneadelapropia
declaracin del mtodo, se opta por la brevedad para evitar declaraciones de clase
excesivamenteextensas.
Laimportanciadelaencapsulacinpuedeponersedemanifiestoenestapequeay
poco til clase. Tal y como est diseada, no es posible que exista incoherencia entre el
contenido del vector de enteros (lista) y el indicador del nmero de enteros introducido
(num),puestoquelosvaloresalmacenadosenambos,sonmodificadosporlosmtodosdela
clase, los cuales se aseguran de que los valores introducidos son vlidos. Al impedir que el
usuario modifique directamente el valor de estos atributos, se evita la aparicin de
incoherenciasyportantoseeliminaunadelasmayoresfuentesdeerror.
Laclaseademsgestionalapropiacapacidaddealmacenamiento,deformaquese
aseguradequenuncaseintroduzcanmsdeciennmeros.Aunqueelusuariopidaintroducir
doscientos nmeros slo se almacenaran cien, puesto que slo se dispone de espacio para
cien.
Por todo esto es muy interesante que los atributos que afectan al funcionamiento
interno de una clase se declaren protegidos ante posibles modificaciones externas y que
siempre se compruebe la validez de los valores solicitados por medio de las distintas
funcionesdeinterfaz.
Sinembargo,enciertasocasiones,sequerrteneraccesoadeterminadosmiembros
privadosdeunobjetodeunaclasedesdeotrosobjetosdeclasesdiferentes.Paraesoscasos
(quedeberanserexcepcionales)C++proporcionaunmecanismoparasortearelsistemade
proteccin. Ms adelante se ver la utilidad de esta tcnica, ahora se limitar a explicar en
queconsiste.ElmecanismodelquesedisponeenC++eseldenominadodeamistad(friend).
Laamistadnopuedeheredarseyaveremoselconceptodeherencia.SiA
esmigodeB,yCesunaclasehijadeB,AnotienequeseramigodeC.(Los
hijosdemisamigos,notienenporquseramigosmos.Denuevo,elsmiles
casiperfectohaycadahijodemisamigos).
Laamistadnoessimtrica.SiAesamigodeB,Bnotieneporqueseramigo
deA.(EnlavidarealunasituacincomoestaharpeligrarlaamistaddeA
con B, pero de nuevo y por desgracia se trata de una situacin muy
frecuenteenlaqueAnosabeloqueBpiensadelbastaconobservarlo
quealgunossoncapacesdedecirdesusamig@sasuespalda).
clasessinembargodeberincluirdentrodesudeclaracinlacopiadelprototipodelafuncin
precedidadelapalabrafriend.
#include <iostream>
class A
{
public:
A(int i) {a=i;};
void Ver() { cout << a << endl; }
private:
int a;
friend void Visualiza(A); //Visualiza es amiga de la clase A
};
void main()
{
A Na(10);
Visualiza(Na); // imprime el valor de Na.a
Na.Ver(); // Equivalente a la anterior
}
Seobservacomolafuncinvisualizaescapazdeaccederdirectamentealmiembro
privadoa,delobjetoNagraciasasucondicindefuncinamigadelaclase.Sienestemismo
ejemplo eliminsemos la lnea de la declaracin de la clase A en la que se define Visualiza
comofuncinamiga,elcompiladordaraunerrorporintentaraccederaunmiembroprivado
delobjetopasadoenXa.
Alfinaldeestecaptuloseintroduceuncdigoextensoqueilustralautilidaddeeste
mecanismo.
Es importante destacar para finalizar que una funcin amiga de una clase, no es
miembrodeesaclase.
class B
{
public:
B(int i){b=i;};
void ver() { cout << b << endl; };
bool esMayor(A Xa); // Compara b con a
private:
int b;
};
class A
{
public:
A(int i=0) : a(i) {}
void ver() { cout << a << endl; }
private:
// Funcin amiga tiene acceso
// a miembros privados de la clase A
friend bool B::esMayor(A Xa);
int a;
};
bool B::esMayor(A Xa)
{
return (b > Xa.a);
}
void main(void)
{
A Na(10);
B Nb(12);
Na.ver();
Nb.ver();
if(Nb.esMayor(Na)) cout << "Nb es mayor que Na" << endl;
else cout << "Nb no es mayor que Na" << endl;
}
Losconstructorestienenelmismonombrequelaclase,noretornanningnvalory
no pueden ser heredados. Adems suelen ser pblicos, dado que habitualmente se usan
desdeelexteriordelaclase.Algunospatronesmsavanzadosdelovistoenestecurso,como
elsingletonhacenusoamenudodeconstructoresprivadosoprotegidos,peroennuestro
casoengenerallosdeclararemoscomopblicos.
Losconstructoressuelenserpblicos.
Siunaclaseposeeconstructor,serllamadosiemprequesedeclareunobjetodeesa
clase, y si requiere argumentos, es obligatorio suministrarlos. Por ejemplo, las siguientes
declaracionessonilegales:
pareja par1;
pareja par1();
La primera porque el constructor de "pareja" requiere dos parmetros, y no se
suministran. La segunda es ilegal por otro motivo ms complejo. Aunque existiese un
constructor sin parmetros, no se debe usar esta forma para declarar el objeto, ya que el
compiladorloconsideracomoladeclaracindeunprototipodeunafuncinquedevuelveun
objetodetipo"pareja"ynoadmiteparmetros.Cuandoseuseunconstructorsinparmetros
paradeclararunobjetonosedebenescribirlosparntesis.
Lassiguientesdeclaracionessonvlidas:
pareja par1(12,43);
pareja par2(45,34);
Cuandonoseespecificaunconstructorparaunaclase,elcompiladorcreaunopor
defectosinargumentosalquesedenominacomoconstructordeoficio.Poresolosejemplos
anterioresfuncionabancorrectamente.Cuandosecreanobjetoslocales,losdatosmiembros
no se inicializan si el programador no se preocupa de hacerlo. Contendran la "basura" que
hubieseenlamemoriaasignadaalobjeto.Curiosamente,sisetratadeobjetosglobales,los
datos miembros se inicializan a cero. Esto se realiza de esta forma porque el proceso de
inicializacin lleva un tiempo. Los objetos locales son por propia definicin temporales y
puedensercreadosmuchasvecesdurantelaejecucindeunprograma,porloquealfinal,el
tiempo de inicializacin puede ser significativo. Por el contrario, los objetos globales son
inicializados al comenzar la ejecucin del programa, por lo que esto se hace una sla vez y
durantelapreparacindelaejecucindelcdigo.
Paradeclararobjetosusandoelconstructorpordefectoounconstructorquesehaya
declaradosinparmetrosnosedebeusarelparntesis:
pareja par2();
pareja par2;
Inicializacin de objetos
Existe un modo simplificado de inicializar los datos miembros de los objetos en los
constructores. Se basa en la idea de que en C++ todo son objetos, incluso las variables de
tiposbsicoscomoint,charofloat.
Segn esto, cualquier variable (u objeto) tiene un constructor por defecto, incluso
aquellos que son de un tipo bsico. Slo los constructores admiten inicializadores. Cada
inicializador consiste en el nombre de la variable miembro a inicializar, seguida de la
expresin que se usar para inicializarla entre parntesis. Los inicializadores se aadirn a
continuacindelparntesiscerradoqueencierraalosparmetrosdelconstructor,antesdel
cuerpodelconstructoryseparadodelparntesispordospuntos":".
Porejemplo,enelcasoanteriordelaclasepareja:
pareja::pareja(int a2, int b2)
{
a = a2;
b = b2;
}
Sepuedesustituirelconstructorpor:
pareja::pareja(int a2, int b2) : a(a2), b(b2) {}
Aligualqueocurreconlasfuncionesglobales,ycomoyaveremosconlosmtodosy
operadores,esposiblesobrecargarelconstructor.Recurdesequelasobrecargasignificaque
bajounmismoidentificadorseejecutancdigosdistintosenfuncindelosargumentosque
se pasen parala ejecucin. Por eso, lanica restriccin en la sobrecarga es que no pueden
definirsedosconstuctoresquenosediferencienenelnmeroytipodelosargumentosque
utilizan.
Paralaclasepalabra,enelsiguienteejemplo,seaadendosnuevosconstructores,el
primerosinargumentosqueinicializalaparejaacero,alquesedenominaconstructorpor
defecto. El segundo, inicializar la pareja por medio de un nmero real del cual extrae el
primerdgitodelapartedecimalylaparteentera.
class pareja
88 PROGRAMACIN C++ Y COMUNICACIONES.
{
public:
// Constructor anterior
pareja(int a2, int b2) : a(a2), b(b2) {}
//contructor por defecto
pareja() : a(0), b(0) {}
//otro constructor
pareja(double num);
// Funciones miembro de la clase "pareja"
void Lee(int &a2, int &b2);
void Guarda(int a2, int b2);
private:
// Datos miembro de la clase "pareja"
int a, b;
};
pareja::pareja(double num)
{
a=(int)num;
b=((int)(num*10))%10;
}
void main()
{
pareja p1,p2(12,3),p3(2.8);
}
Laparejap1serentoncesinicializadaconlosvalores(a=0,b=0),p2con(a=12,b=3)y
p3con(a=2,b=8).Deestemodosepuedendefinirmuchasmanerasdeinicializarlosobjetos
deunaclase.
Al igual que cualquier funcin, es posible definir valores por defecto para los
parmetros.Elinconvenienteesquesiexistendosfuncionesquetienendefinidosvalorespor
defectodetodossusargumentos,seproducirunaambigedadalahoradedefinircualde
lasdossetienequeejecutar.Elcompiladorinformardeestasituacin,yencasodequesea
necesario utilizar el constructor por defecto en alguna parte del cdigo es posible que
aunquesehayadefinidonosehagausodelentoncesgenerarunerrordecompilacin.
Porejemplo,elcompiladornopermitiralaejecucindelsiguienteprograma:
#include <iostream.h>
#include <math.h>
class pareja
{
public:
// Constructor anterior con valores por defecto
pareja(int a2=0, int b2=0) : a(a2), b(b2) {}
void main()
{
pareja p1;
pareja p2(12,3),p3(2.8);
int a,b;
p1.Lee(a,b);
cout<<a<<','<<b;
}
eindicaraelsiguienteerrorenlalneadedeclaracindep1:
pareja::pareja':ambiguouscalltooverloadedfunction
El constructor de copia
Existeotrotipodeconstructorespecialqueencasodequelprogramadornodefina
el compilador asigna uno de oficio. Este es el llamado constructor de copia, y que como su
propionombreindicasirveparainicializarunobjetocomocopiadeotro.
Paraelejemploparejasepodraescribirlosiguiente:
class pareja
90 PROGRAMACIN C++ Y COMUNICACIONES.
{
pareja(const pareja &p):a(p.a),b(p.b){}
}
void main(void)
{
pareja p1(12,32);
pareja p2(p1); //Uso del constructor de copia
}
El destructor
El complemento a los constructores de una clase es el destructor. As como el
constructorsellamaaldeclararocrearunobjeto,eldestructoresllamadocuandoelobjeto
vaadejardeexistirporhaberllegadoalfinaldesuvida.Enelcasodequeunobjetolocal
haya sido definido dentro de un bloque {}, el destructor es llamado cuando el programa
llegaalfinaldeesebloque.
Si el objeto es global o static su duracin es la misma que la del programa, y por
tantoeldestructoresllamadoalterminarlaejecucindelprograma.Losobjetoscreadoscon
reserva dinmica de memoria (en general, los creados con el operador new) no estn
sometidos a las reglas de duracin habituales, y existen hasta que el programa termina o
hasta que son explcitamente destruidos con el operador delete. En este caso la
responsabilidadesdelprogramador,ynodelcompiladorodelsistemaoperativo.Eloperador
delete llama al destructor del objeto eliminado antes de proceder a liberar la memoria
ocupadaporelmismo.
A diferencia del constructor, el destructor es siempre nico (no puede estar
sobrecargado) y no tiene argumentos en ningn caso. Tampoco tiene valor de retorno. Su
nombre es el mismo que el de la clase precedido por el carcter tilde (~), carcter que se
consigueconAlt+126eneltecladodelPComedianteelusodelosdenominadostrigrafos(??
).Lostrigrafossonconjuntosdecaracteresprecedidospor??queelpreprocesadorconvierte
auncarcteravecesnopresenteenalgunostecladosoidiomas.Portanto,paraelordenador
eslomismollegaraescribirelcarcter~queelconjuntodecaracteres??.
Enelcasodequelaclaseparejanecesitaseundestructor,ladeclaracinseraas:
~pareja();
Elsiguienteejemplomuestrauncasoenelqueesnecesarioalmacenarunacadena
decaracteresdetamaovariable,porloquealsereliminadoelobjetoesnecesarioliberarla
memoriareservadadeformadinmica:
class persona
{
public:
persona(const char *nom, long dni);
persona():nombre(NULL),DNI(0){};
??-persona(); //podra haberse escrito ~persona();
void mostrar();
private:
char *nombre;
long DNI;
};
persona::persona(const char *nom,long dni)
{
nombre=new char[strlen(nom)+1];
strcpy(nombre,nom);
DNI=dni;
cout<<"Construyendo "<<nombre<<endl;
}
Elresultadodeejecutaresteprogramaeselsiguiente:
Construyendo dura todo el main
Construyendo Dura el ciclo del for
almacenado:Dura el ciclo del for DNI:0
Destruyendo Dura el ciclo del for
Construyendo Dura el ciclo del for
almacenado:Dura el ciclo del for DNI:1
Destruyendo Dura el ciclo del for
Destruyendo dura todo el main
Loquepermitevisualizarcomohansidollamadoslosconstructoresydestructoresde
losobjetosquesehancreado.
Mtodos sobrecargados
En el captulo de modificaciones menores a C, uno se los puntos que se vio era la
posibilidadqueofreceC++paraescribirvariasfuncionesqueteniendoelmismoidentificador
eran diferenciadas por el tipo de parmetros utilizado. De esta forma se facilitaba la
comprensindelcdigoylafacilidaddeprogramacinalevitareltenerqueutilizarnombres
distintosparatiposdeargumentosdistintoscuandolafuncionalidadesparecida.
Bueno, pues este mismo concepto es aplicable a los mtodos de una clase. Baste
parailustrarloelsiguienteejemplo:
#include <iostream>
struct punto3D
{
float x, y, z;
};
class punto
{
public:
void Asignar(float xi, float yi, float zi)
{
x = xi;
y = yi;
z = zi;
}
void Asignar(punto3D p)
{
Asignar(p.x, p.y, p.z);
}
void Ver()
{
cout << "(" << x << "," << y
<< "," << z << ")" << endl;
}
private:
float x, y, z;
};
void main(void)
{
punto3D p3d = {32,45,74};
P.Asignar(p3d);
P.Ver();
P.Asignar(12,35,12);
P.Ver();
}
Operadores sobrecargados
En C++ los operadores pasan a ser unas funciones como otra cualquiera, pero que
permiten para su ejecucin una notacin especial. Todos ellos tienen asignada una funcin
pordefectoqueeslaquehastaahorahabamosutilizadoenC.Porejemplo,eloperador+
realizarlasumaaritmticaolasumadepunterosdelosoperandosquepongamosaambos
lados.
Apartirdeahora,podremoshacerqueeloperador+realiceaccionesdistintasen
funcin de la naturaleza de los operandos sobre los que trabaja. De hecho, en realidad, la
mayora de los operandos en C++ estn sobrecargados. El ordenador realiza operaciones
distintas cuando divide enteros que cuando divide nmeros en coma flotante. Un ejemplo
ms claro sera eldel operador *,que enunoscasos trabaja como multiplicadory en otros
realizalooperacindeindireccin.
EnC++elprogramadorpuedesobrecargarcasitodoslosoperadoresparaadaptarlos
asuspropiosusos.Paraellodisponemosdeunasintaxisespecficaquenospermitedefinirlos
odeclararlosaligualqueocurreconlasfunciones:
Sepuedensobrecargartodoslosoperadoresexcepto.,.*,::,?:.
Al menos uno de los argumentos para los operadores externos deben ser
tiposenumeradosoestructurados:struct,enum,unionoclass.
Eloperador>deberetornarunpunterosobreelquesepuedaaplicarel
accesoalcampocorrespondiente.
void main()
{
complex a={5.0F,3.0F},b={3.0F,1.2F},c;
c=a+b;
cout<<c.real<<"+"<<c.imag<<"i"<<endl;
}
Puesto que lo que se ha sobrecargado es el operador suma con dos operandos, es
necesarioqueaparezcantantoenelprototipocomoenladefinicinestosdosoperandoscon
sutipo.Esfcildeducirqueconestasintaxissepodrngeneraroperadoressumaquesean
capacesdesumarvectoresycomplejosyquesuresultadoseaunamatriz.Comosiempre,C++
nosdaunaherramientaqueclarificaelcdigo,perosiguedependiendodelprogramadorque
suusosealgico.
Portanto,enladeclaracindelaclaseseincluirunalneaconlasiguientesintaxis:
Habitualmente<tipo>serparaunobjetodelamismaclase,peronoesnecesario.
Aselcasomshabitualesquesiestamossumandocomplejos,elprimerysegundooperador
seandetipocomplejoyelresultadouncomplejo.
Sinembargonotieneporqueserdeestamanera.Porejemploenelcasodeoperar
conmatrices,esperfectamentevlidodefinirunaoperacinproductoentreunamatrizyun
vector,objetosdedosclasesdistintas,ycuyoresultadoesunvector.Silaoperacinproducto
96 PROGRAMACIN C++ Y COMUNICACIONES.
estdefinidaenelinteriordelaclasematriz,elargumentoserdetipovectoryelvalorde
retornotambin.
Semostrarunejemplosencillo,quepermiteoperarconvaloresdetiempodeforma
sencilla. En esta clase se definir el operador suma de tal forma que se puedan sumar
periodosdeduracinmedidosenhorasyminutos.
#include <iostream.h>
class Tiempo
{
public:
Tiempo(int h=0, int m=0) : hora(h), minuto(m) {}
void Mostrar(){cout << hora << ":" << minuto << endl;};
Tiempo operator+(Tiempo h);
private:
int hora;
int minuto;
};
Tiempo Tiempo::operator+(Tiempo h)
{
Tiempo temp;
temp.minuto = minuto + h.minuto;
temp.hora = hora + h.hora;
if(temp.minuto >= 60){
temp.minuto -= 60;
temp.hora++;
}
return temp;
}
void main(void)
{
Tiempo Ahora(12,24), T1(4,45);
T1 = Ahora + T1;
T1.Mostrar();
(Ahora + Tiempo(4,45)).Mostrar(); //(1)
}
En este ejemplo se ha introducido una de las posibilidades que ofrece C++ hasta
ahora no comentada ni utilizada. En el punto del cdigo marcado con (1), se utiliza una
instanciadelaclasesinhaberledadounnombre.Esdecir,Tiempo(4,5)creaunobjetoqueno
podremosreferenciarposteriormenteunavezejecutadalasentenciapuestoquenolehemos
asignadoningnidentificador.Sinembargoelobjetoexistirypodrserutilizado,deforma
queen(1)seestdiciendoquesesumealtiempoguardadoenAhorauntotalde4horasy45
minutos.
Igualesmuchodegolpe,peroesmomentodecomenzarairviendocdigomsreal.
Acontinuacinserealizarunasobrecargadeloperadorsumadetalformaqueala
horalevamosasumarslominutos.Enesecaso,eloperadorsumarecibircomosegundo
operandounvalorentero,ydarcomoresultadounobjetoTiempo.
#include <iostream.h>
class Tiempo
{
public:
Tiempo(int h=0, int m=0) : hora(h), minuto(m) {};
void Mostrar(){cout << hora << ":" << minuto << endl;};
Tiempo operator+(Tiempo h);
Tiempo operator+(int mins);
private:
int hora;
int minuto;
};
Tiempo Tiempo::operator+(Tiempo h)
{
Tiempo temp;
temp.minuto = minuto + h.minuto;
temp.hora = hora + h.hora;
if(temp.minuto >= 60)
{
temp.minuto -= 60;
temp.hora++;
}
return temp;
}
Tiempo Tiempo::operator +(int mins)
{
Tiempo temp;
temp.minuto=minuto+mins;
temp.hora=hora+temp.minuto/60;
temp.minuto=temp.minuto%60;
return temp;
}
void main(void)
{
Tiempo Ahora(12,24), T1(4,45);
T1 = Ahora + T1;
T1.Mostrar();
(Ahora+45).Mostrar();
}
98 PROGRAMACIN C++ Y COMUNICACIONES.
Denuevosehautilizadounobjetotemporalqueeselretornadoporeloperador+.El
compilador diferencia a cual de las dos operaciones suma hacemos referencia gracias al
distinto tipo de operandos utilizado en cada caso. As, en la primera suma se ejecuta el
operadorparasumardostiempo,mientrasqueenlasegundaseejecutareloperadorque
permitelasumadeuntiempoyunosminutos.
ObsrveseaunqueestoestemadeCcmoseaprovechaelmodoenqueCopera
distintoconlosnmerosencomaflotanteylosenterosparapodertransformarlosminutos
enlashorasyminutoscorrespondientes.
Sobrecargadeloperadorigual.
Unoperadorqueamenudoesnecesariosobrecargareseloperadorigual.Sinose
sobrecarga este operador, el compilador asignar uno por defecto (como en el caso del
ejemplo) querealizar unacopia literal de lo que hay enla memoria de un objeto sobre el
otro. Este operador por defecto es vlido siempre que no se est utilizando memoria
dinmica,peropuedecrearautnticosquebraderosdecabezaencasocontrario.
Unejemplotpicodeestasituacineseldeunaclaseconcapacidaddealmacenar
frases tan largas como se quiera: la clase cadena. El siguiente cdigo no funcionar como
deseamos,yposiblementenosdemuchosproblemas:
class Cadena
{
public:
Cadena(char *cad);
Cadena() { cadena=NULL;} ;
~Cadena() { delete[] cadena; };
void Mostrar(){cout << cadena << endl;};
void RellenarDeGuiones();
private:
char *cadena;
};
Cadena::Cadena(char *cad)
{
cadena = new char[strlen(cad)+1];
strcpy(cadena, cad);
}
void Cadena::RellenarDeGuiones()
{
for(int i=0;i<strlen(cadena);i++)
cadena[i]=-;
}
Siejecutamoselsiguienteprograma,seobservaqueelresultadodistamuchodeser
elesperadoademsdegenerarunerroralfinalizarselaejecucin:
void main(void)
{
Cadena C1(Hola Mundo), C2(Qu tal?); //(1)
C1.Mostrar();
C2.Mostrar();
C1=C2; //(2)
C2.RellenarDeGuines(); //(3)
C1.Mostrar();
C2.Mostrar();
}
Encontradeloquepuedaparecer,enlaimpresinsegundaimpresindeC1yC2,en
pantalla aparecen solo guiones para ambas cadenas Por qu, si en el cdigo solo se ha
indicadoelrellenodeguionesparaC2?PorquesmodificadoC1?.
Las tres columnas siguientes muestran el estado de C1 y C2 en (1), (2), y (3) en la
memoria, en donde como es habitual el contenido del puntero es representado por una
flecha.
COPIA
1000 1000 1000
C1 C1 C1
Cadena = 1050 Cadena = 1150 Cadena = 1150
Elcdigopararealizaresteoperadorseraelsiguiente:
Cadena &Cadena::operator=(const Cadena &c)
{
if(this != &c)
{
delete[] cadena;
if(c.cadena)
{
cadena = new char[strlen(c.cadena)+1];
strcpy(cadena, c.cadena);
}
else cadena = NULL;
}
return *this;
}
Al manejar punteros hay que tener una serie de precauciones que aparecen de
manifiesto en este ejemplo. Por ejemplo, inicialmente se comprueba que no se est
realizandounaasignacindeunaCadenasobresmisma.Secompruebaantessiexisteuna
cadena en el objeto cadena pasado, y no hubiera estado de ms comprobar que existe un
espacioreservadoenlamismacadenaantesdeprocederaeliminarla.Graciasalpunterothis
estasoperacionessehanpodidorealizarsinproblema.
Es muy habitual que el operador = retorne una referencia al propio objeto para
permitir realizar asignaciones concatenadas sin necesidad de crear un objeto temporal.
Gracias a esta referencia ser posible escribir sentencias del estilo: C1=C2=C3 tal y como
sucedeconlasasignacionesenlostiposbsicos.
Ademsdeloperador+puedensobrecargarseprcticamentetodoslosoperadores:
+, -, *, /, %, ^, &, |, (,), <, >, <=, >=, <<, >>, ==,
!=, &&, ||, =, +=. -=, *=, /=, %=, ^=, &=, |=, <<=,>>=, [ ],
(),->, new y delete.
OtroejemploparalaclaseTiemposeraeldeloperador+=,quealigualqueconlos
tiposbsicosrealizarlasumasobreelprimeroperandodelsegundo.
class Tiempo
{
...
void operator+=(Tiempo h);
...
102 PROGRAMACIN C++ Y COMUNICACIONES.
};
void Tiempo::operator+=(Tiempo h)
{
minuto += h.minuto;
hora += h.hora;
while(minuto >= 60)
{
minuto -= 60;
hora++;
}
}
void main(void)
{
...
Ahora += Tiempo(1,32);
Ahora.Mostrar();
...
}
Noesimprescindiblemantenerelsignificadodelosoperadores.Porejemplo,parala
claseTiemponotienesentidosobrecargareloperadores>>,<<,*/,perosepuededetodos
modos,yolvidarelsignificadoquetenganhabitualmente.
Deigualmodosepodrahabersobrecargadoeloperador+yhacerquenosumara
lostiempossinoque,porejemplo,losrestara.Enltimainstancia,eselprogramadorelque
decideelsignificadodelosoperadores.
Sinembargo,comonormageneral,esconvenientedecaraaobteneruncdigoms
legiblequelafuncionalidaddeloperadorseaanlogaasusignificado.
Sobrecargadeloperador>>y<<.
Porsuaplicacinmshabitualseconsiderarbrevementeelcasodelosoperadores
binariosdedesplazamientoodeinsercinyextraccinenunflujodedatos.Enprimerlugar
hayqueaclararquenosetratadeunoperadornuevo,sinoqueeselquesehaescogidopara
insertarinformacinenlosiostream.Portantosepuedeutilizarparacualquierotraoperacin
queconsideremosoportuna.Sinembargolomshabitualesrespetaresteusorealizadopor
lalibreraestndar,yademsenmuchoscasosadherirnosaestemododetransmitirorecibir
lainformacindeunobjeto.
puesto que pertenece a la STL. Por ello, la sobrecarga del operador de insercin se realiza
comounafuncinexterna,yadems,comohabitualmentesernecesarioaccederalaparte
provadadelobjetoparapoderimprimirlo,sedeclaracomofuncinamigadelaclase.
El aspecto que tiene la sobrecarga tanto del operador >> como <<, siguiendo la
formamscomnderealizarseeselsiguiente:
ostream & operator<< (ostream &os, const MI_CLASE &obj)
istream & operator>> (istream &is, MI_CLASE &obj)
Los flujos de salida, gracias a la herencia, podremos agruparlos de forma genrica
dentro del concepto ostream. Por tanto cout, es un objeto de tipo ostream. Los flujos de
entradaserndeltipoistream.Parapoderconcatenarinsercionesyextracciones,elresultado
de la operacin es el mismo flujo sobre el que se ha extraido o insertado. Pongamos como
ejemploestosoperadoresparalaclaseTiempo:
class Tiempo
{
...
friend ostream & operator<< (ostream &os, const Tiempo &t)
friend istream & operator>> (istream &is, Tirmpo &t)
...
};
ostream & operator<< (ostream &os, const Tiempo &t)
{
os<<t.hora<<:<<t.minuto;
return os;
}
istream & operator>> (istream &is, Tiempo &t)
{
string a;
is>>a;
int index=a.find_first_of(:);
if(index!=string::nppos){
t.hora=stoi(a.substring(0,index);
t.minuto=stoi(a.substring(index+1));
}
return is;
}
void main()
{
Tiempo t1;
cin>>t1;
cout<<Tiempo ledo = <<t1<<endl;
}
104 PROGRAMACIN C++ Y COMUNICACIONES.
Normalmenteel<tipo>eslaclaseparalaqueestamossobrecargandoeloperador,
pero al igual que ocurra con los operadores binarios, esto es algo que queda a la libre
eleccindelprogramador.
ComoejemploserealizareloperadordeincrementoparalaclaseTiempoqueseha
venidodefiniendohastaahora.
class Tiempo
{
...
Tiempo operator++();
...
};
Tiempo Tiempo::operator++(){
minuto++;
while(minuto >= 60)
{
minuto -= 60;
hora++;
}
return *this;
}
void main(void){
...
T1.Mostrar();
++T1;
T1.Mostrar();
...
}
Sinembargo,existendosversionesparaeloperadorincremento,elpreincrementoy
elpostincremento.Elejemplomostradoeslasobrecargadeloperadorpreincrementopara
laclaseTiempo,cmosesobrecargaeloperadordepostincremento?
En realidad no hay forma de decirle al compilador cul de las dos modalidades del
operador se est sobrecargando, as que los compiladores usan una regla: si se declara un
parmetroparaunoperador++sesobrecargarlaformasufijadeloperador.
Elparmetroseignorar,asquebastarconindicareltipo.
Tambintenemosquetenerencuentaelpeculiarfuncionamientodelosoperadores
sufijos, cuando se sobrecarguen, al menos si se quiere mantener el comportamiento que
tienennormalmente.
Cuandoseusaunoperadorenlaformasufijodentrodeunaexpresin,primerose
usa el valor actual del objeto, y una vez evaluada la expresin, se aplica el operador. Si se
quierequeeloperadoracteigualsedebeusarunobjetotemporal,yasignarleelvaloractual
del objeto. Seguidamente se aplica el operador al objeto actual y finalmente se retorna el
objetotemporal.
class Tiempo
{
...
Tiempo operator++(); // Forma prefija
Tiempo operator++(int); // Forma sufija
...
};
Tiempo Tiempo::operator++()
{
minuto++;
while(minuto >= 60)
{
minuto -= 60;
hora++;
}
return *this;
}
Tiempo Tiempo::operator++(int)
{
Tiempo temp(*this); // Constructor copia
minuto++;
while(minuto >= 60)
{
minuto -= 60;
106 PROGRAMACIN C++ Y COMUNICACIONES.
hora++;
}
return temp;
}
void main(void)
{
T1.Mostrar();
(T1++).Mostrar();
T1.Mostrar();
(++T1).Mostrar();
T1.Mostrar();
}
Elresultadodeejecutarestapartedelprogramaser
17:9 (Valorinicial)
17:9 (Operadorsufijo,elvalornocambiahastadespusdemostrarelvalor)
17:10(Resultadodeaplicareloperador)
17:11(Operadorprefijo,elvalorcambiaantesdemostrarelvalor)
17:11 (Resultadodeaplicareloperador)
Uncasoparticulardelosoperadoresunarioseseldelasconversionesdetipo.Para
ilustrar su utilidad y cuando aparecen se continuar con el ejemplo de la clase Tiempo.
Supongasequesequiererealizarunaoperacincomolasiguiente:
Tiempo T1(12,23);
unsigned int minutos = 432;
T1 += minutos;
Elvalordeseado,queserasumarlosminutosindicadosaltiempoalmacenadoenT1,
no se calcular correctamente. Lo que ocurre cuando se ejecuta la tima sentencia es lo
siguiente.EnC++serealizanconversionesimplcitasentrelostiposbsicosantesdeoperar
con ellos. Por ejemplo, para sumar un int y un float se promociona (convierte) el entero a
floatydespusserealizalaoperacinentredosnmerosdelmismotipo,siendoentoncesel
resultadodelamismaunfloat.
Estoesloqueocurrirconlaexpresindelejemplo.Elvalordeminutosseintentar
convertiraunobjetoTiempo,puestoqueeloperador+=definidoesperaunobjetodeeste
tipo como operando. Para ello se utilizar el constructor diseado. Como slo hay un
parmetro,yambos tienendefinidos valores por defecto, entonces elparmetro h toma el
valor de minutos, y el valor de m toma el de por defecto (o sea 0). El tipo de h es de tipo
entero,porloqueseconvierteelvalorunsignedintaintyseejecutaelconstructor.
Elresultadoesquesesuman432horas,ycuandoloquesedeseabaerasumar432
minutos. Esto se soluciona creando un nuevo constructor que tome como parmetro un
unsigned int, de forma que el compilador diferencia la operacin que tiene que realizar
graciasaltipodelargumento:
Tiempo(unsigned int m) : hora(0), minuto(m)
{
while(minuto >= 60)
{
minuto -= 60;
hora++;
}
}
La palabra clave explicit sirve para evitar que el compilador realice conversiones
implcitasmedianteunconstructorespecfico.
Sinembargo,esinteresantevercomosetrabajaenelcasoinverso.Esdecir,ahoralo
que se deseaes dotar a C++ de mecanismos para convertir una instancia de la clase a otro
tipo.Porejemplo,sedeseaahoraasignaraunenteroelvalorcontenidoenTiempo.Laideaes
quesedeseatransformarlashorasyminutoseneltotaldeminutosquerepresentan:
Tiempo T1(12,23);
int minutos;
minutos = T1;
En este caso se obtendra un error de compilacin, ya que el compilador no sabe
convertirunobjetoTiempoaentero.Parapoderrealizarestaoperacinsedeberdisearun
operadordeconversindetipoqueilustrealcompiladordequeoperacionesdeberrealizar
paraobtenerelenteroequivalenteaunobjetoTiempo.
Losoperadoresdeconversindetipotienenelsiguienteformato:
operador <tipo>();
No necesitan que se especifique el tipo del valor de retorno, ya que este es
precisamente <tipo>. Adems, al ser operadores unitarios, tampoco requieren argumentos,
puestoqueseaplicanalpropioobjeto.
class Tiempo
{
...
operator int();
...
}
Tiempo::operator int()
{
return hora*60+minuto;
}
Por supuesto, el tipo no tiene por qu ser un tipo bsico, puede tratarse de una
estructuraounaclase.
Los operadores [ ] y ( )
El operador de indexacin
El operador [ ] se usa para acceder a valores de objetos de una determinada clase
como si se tratasen de arrays. Los ndices no tienen por qu ser de un tipo entero o
enumerado,ahoranoexisteesalimitacin.
Dondemstilresultaesteoperadorescuandoseusaconestructurasdinmicasde
datos:listas,rboles,vectoresdinmicos,etc.Perotambinpuedeservirparacreararrays
asociativos,dondelosndicesseanporejemplo,palabras.
Denuevoseexplicarelusodeesteoperadorusandounejemplo.Lasiguienteclase
permite obtener el valor resultante de interpolar entre los valores de un vector de n
componentes,enfuncindeunindicequeenvezdeserenteroesreal:
#include <iostream.h>
#include <math.h>
class vector
{
public:
vector(int n=0,double *v=NULL);
double operator[](double ind);
~vector(){delete [] valores;}
private:
int num;
double *valores;
};
vector::vector(int n,double *v)
{
valores = new double[n];
num=n;
for(int i=0;i<n;i++)valores[i]=v[i];
}
double vector::operator [](double ind)
{
double temp;
int sup,inf;
inf=(int)floor(ind); //entero redondeado abajo
sup=(int)ceil(ind); //entero redondeado arriba
if(inf>num-1)inf=num-1;
if(sup>num-1)sup=num-1;
if(inf<0)inf=0;
if(sup<0)sup=0;
if(inf<sup)
temp=(sup-ind)*valores[inf]+(ind-inf)*valores[sup];
else temp=valores[inf];
return temp;
}
void main(void)
{
double val[4]={1.0,4.0,-1.0,2.0};
110 PROGRAMACIN C++ Y COMUNICACIONES.
vector mivector(4,val);
for(int i=0;i<31;i++)
cout<<mivector[i*0.1]<<endl;
}
Elprogramamostrarlosvaloresintermediosde0.1en0.1.Sehautilizadounvalor
doublecomondice,perodeigualformasepodrahaberutilizadounacadenadecaracteres
ounobjeto.
Cuando se combina el operador de indexacin con estructuras dinmicas de datos
comolaslistas,sepuedetrabajarconellascomosisetratadadearraysdeobjetos,estodar
unagranpotenciayclaridadalcdigodelosprogramas.
El operador llamada
El operador llamada ( ) funciona exactamente igual que el operador [], aunque
admite ms parmetros. Este operador permite usar un objeto de la clase para el que est
definidocomosifueraunafuncin.
Portantoelnmerodeparmetrosyelvalorderetornodependerntotalmentede
loquedecidaelprogramador.Paraelejemploanteriorsevaaampliareloperadorindexacin
definido,deformaquesiseutilizaeloperadorllamadasepudeescogersisedesearealizarla
interpolacinono:
class vector
{
double operator()(double ind,bool interpolar=true);
}
double vector::operator ()(double ind,bool interpolar)
{
if(interpolar)return (*this)[ind];
else return valores[(int)ind];
}
void main(void)
{
double val[4]={1.0,4.0,-1.0,2.0};
vector mivector(4,val);
for(int i=0;i<31;i++)
{
cout<<mivector[i*0.1]<< ;
cout<<mivector(i*0.1,false)<<endl;
}
}
Atributos static
En ocasiones se hace necesario de disponer de una variable comn a todos los
objetos de una clase. Por ejemplo, si se quisiera llevar cuenta de cuantos objetos se han
creadodeunaclasedeterminada,sedeberateneruncontadorquefueracomnatodoslos
objetos.EstafuncionalidadesproporcionadaenC++pormediodelosmiembrosestticosde
unaclase.
Para ilustrar esto se va a definir una clase libro sencilla, que permitir asignar un
identificadornicoacadalibrocreado.
#include <iostream.h>
#include <string.h>
class libro
{
public:
libro (const char *tit, const char *aut);
~libro();
void mostrar();
static int contador; //(1)
private:
char *titulo;
char *autor;
int ID;
};
libro::~libro()
{
delete [] titulo;
delete [] autor;
}
void libro::mostrar()
{
cout<<"Libro "<<ID<<": \t"<<titulo<<endl;
cout<<"\t\t"<<autor<<endl<<endl;
}
void main(void)
{
libro l1("Cucho","Olaizola");
libro l2("Tuareg","Vazquez Figueroa");
libro l3("El Quijote","Cervantes");
l1.mostrar();
l2.mostrar();
l3.mostrar();
}
Elresultadodeejecutarestecdigoeselsiguiente:
Libro 1: Cucho
Olaizola
Libro 2: Tuareg
Vazquez Figueroa
Libro 3: El Quijote
Cervantes
Unatributostaticnoesunatributoespecficodeunobjeto(comoeselcasodelos
atributosautor,titulooID)sinoquemsbienesunatributodelaclase;estoes,unatributo
delqueslohayunacopiaquecompartentodoslosobjetosdelaclase.Porestemotivo,un
atributostaticexisteypuedeserutilizadoaunquenoexistaningunobjetodelaclase.
Se observa como para declarar un atributo static basta con anteponer static a la
declaracindentrodelaclase.Dehechoelniveldeacceso(privado,pblicooprotegido)se
mantiene vlido para los atributo y mtodos de tipo esttico. En el ejemplo, la declaracin
puedeverseen(1).
Sinembargoesnecesarioinicializar(yportantocrear)lavariableestticaenalgn
momentoyademsslounavez.Esdecir,tienequeserinicializadoanivelglobalyhayque
asegurarse de que esta inicializacin no se realiza ms veces. Es por ello que es necesario
escribirlalnea(2),enlaquesedicequeelatributodelaclaselibrollamadocontadordetipo
enterovalecuandoescreado0.
Lainicializacindeunatributoestticosecolocageneralmenteenelficherofuente
.cppquecontienelasdefinicionesdelosmtodosdelaclase,puestoqueelcompiladorlee
este fichero una sola vez, mientras que el fichero de cabecera (.h) de definicin de la clase
puede ser incluido multitud de veces, lo que provocara multitud de inicializaciones con el
consiguienteerrordeinicializacin.
Porlodems,unatributoestticonosediferenciadelrestodeatributosyesposible
accederalmismodeigualformaqueocurreconlosatributosnormales(3).
Sin embargo, al ser un atributo que pertenece a la clase y no a un objeto en
particular, es una variable que existe desde el principio del programa No sera posible
accederasuvalorsinnecesidaddecrearunobjeto?.Larespuestaesques.
Porejemplo,elsiguientemainseraperfectamentevlido:
void imprimirLibros()
{
libro l1("Cucho","Olaizola");
libro l2("Tuareg","Vazquez Figueroa");
libro l3("El Quijote","Cervantes");
l1.mostrar();
l2.mostrar();
l3.mostrar();
}
void main(void)
{
cout<<"Numero inicial de libros:";
cout<<libro::contador<<endl;
imprimirLibros();
cout<<"Libros creados:";
cout<<libro::contador<<endl;
}
Obsrvese que una traduccin literal de lo escrito es totalmente coherente con lo
explicado.Laexpresinlibro::contadorsignificaelatributocontadorpertenecientealaclase
libro. Ntese que en el cuerpo del main no existe ninguna variable de tipo libro con la que
114 PROGRAMACIN C++ Y COMUNICACIONES.
acceder al atributo, pero como esta es global y existe para todos los objetos, es posible
obtenerydarleunvalordesdecualquiersitio.
Evidentemente,hasidoposibleaccederalvalordelatributocontadorporseresteun
atributopblico.Sinembargoparecelgicoquedichoatributofueraunatributoprivado.Si
reescribiramos la clase libro con el atributo contador como miembro privado esttico,
entonceselcompiladornopermitiralaconsultadelmismofueradeunobjetodelaclase.
Siempre nos queda la opcin de crear un mtodo de interfaz que a travs de un
objetodelaclasenosremitieraelvalordelcontador.SinembargoC++nosdalaposibilidad
deconsultarestetipodeatributosydemodificarsuvaloraunsiendoprivadospormediode
losmtodosestticoscomoseveracontinuacin.
Metodos static
Unmtododeclaradocomostaticcarecedelpunterothisporloquenopuedeser
invocado para un objeto de su clase, sino que se invoca en general all donde se necesite
utilizarparalaoperacinparalaquehasidoescrito.Desdeestepuntodevistaesimposible
queunmtodostaticpuedaaccederaunmiembronostaticdesuclase;porlamismarazon,
si puede acceder a un miembro static. Luego si un objeto llama a un mtodo static de su
clase,hayquetenerencuentaquenopodraccederaningunodesusatributosparticulares,
apesardequesumododeusonodifieredecualquierotromtododelaclase.
Si reescribimos la clase libro con las modificaciones indicadas al final del anterior
epgrafe,seranecesariounmtodostaticparapoderconsultarelvalordelatributocontador
queahoraesprivado.Aligualqueocurraconlosatributos,unmtodosedeclaraestticoen
ladeclaracindelaclase,peronoesnecesario(dehechonohayquehacerlo)enelmomento
enelquesedefineelmtodo.
Elsiguienteejemploilustraestosaspectosascomoelmododellamaraunmtodo
static sin necesidad de crear un objeto de la clase. Antes de transcribir el mismo hay que
destacar que la utilidad de los miembros static de una clase, no es fcil descubrirla en la
primeraimpresin,peroamedidaquesevaaprendiendoaprogramarenC++secomprueba
la gran utilidad y la facilidad con que se resuelven muchos problemas gracias a esta
herramienta.
#include <iostream.h>
#include <string.h>
class libro
{
public:
libro (const char *tit, const char *aut);
~libro();
void mostrar();
static int getContador(){return contador;};
private:
char *titulo;
char *autor;
int ID;
static int contador;
};
int libro::contador=0;
libro::~libro()
{
delete [] titulo;
delete [] autor;
}
void libro::mostrar()
{
imprimirLibros();
cout<<"Libros creados:";
cout<<libro::getContador()<<endl;
}
3.7. Ejercicios
Elsiguientecdigoextradodelaredrealizaunaclaseparaoperarcmodamentecon
nmeroscomplejos.Algunasdelassolucionesadoptadastienenfinalidadpuramentedocente
paramostrarcasitodoslosaspectosdeestecaptulo:
/******************** fichero Complejo.h**************************/
// fichero Complejo.h
// declaracin de la clase Complejo
#ifndef __COMPLEJO_H__
#define __COMPLEJO_H__
#include <iostream.h>
class Complejo
{
private:
double real;
double imag;
public:
// Constructores
Complejo(void);
explicit Complejo(double, double im=0.0);
Complejo(const Complejo&);
// Set Cosas
void SetData(void);
void SetReal(double);
void SetImag(double);
// Get Cosas
double GetReal(void){return real;}
double GetImag(void){return imag;}
// Sobrecarga de operadores aritmticos
Complejo operator+ (const Complejo&);
Complejo operator- (const Complejo&);
Complejo operator* (const Complejo&);
Complejo operator/ (const Complejo&);
// Sobrecarga del operador de asignacin
Complejo& operator= (const Complejo&);
// Sobrecarga de operadores de comparacin
friend int operator== (const Complejo&, const Complejo&);
friend int operator!= (const Complejo&, const Complejo&);
// Sobrecarga del operador de insercin en el flujo de salida
friend ostream& operator<< (ostream&, const Complejo&);
};
#endif
/******************** fichero
Complejo.cpp**************************/
#include "Complejo.h"
// constructor por defecto
Complejo::Complejo(void)
{
real = 0.0;
imag = 0.0;
}
// constructor general
Complejo::Complejo(double re, double im)
{
real = re;
imag = im;
}
// constructor de copia
Complejo::Complejo(const Complejo& c)
{
real = c.real;
imag = c.imag;
}
// funcin miembro SetData()
void Complejo::SetData(void)
{
cout << "Introduzca el valor real del Complejo: ";
cin >> real;
cout << "Introduzca el valor imaginario del Complejo: ";
cin >> imag;
}
void Complejo::SetReal(double re)
{
real = re;
}
void Complejo::SetImag(double im)
{
imag = im;
}
// operador miembro + sobrecargado
Complejo Complejo::operator+ (const Complejo &a)
{
Complejo suma;
suma.real = real + a.real;
118 PROGRAMACIN C++ Y COMUNICACIONES.
}
// operador friend << sobrecargado
ostream& operator << (ostream& co, const Complejo &a)
{
co << a.real;
long fl = co.setf(ios::showpos);
co << a.imag << "i";
co.flags(fl);
return co;
}
/**************fichero main.cpp**************************/
#include "Complejo.h"
void main(void)
{
// se crean dos Complejos con el constructor general
Complejo c1(1.0, 1.0);
Complejo c2(2.0, 2.0);
// se crea un Complejo con el constructor por defecto
Complejo c3;
// se da valor a la parte real e imaginaria de c3
c3.SetReal(5.0);
c3.SetImag(2.0);
// se crea un Complejo con el valor por defecto (0.0) del 2
argumento
Complejo c4(4.0);
// se crea un Complejo a partir del resultado de una expresin
// se utiliza el constructor de copia
Complejo suma = c1 + c2;
// se crean tres Complejos con el constructor por defecto
Complejo resta, producto, cociente;
// se asignan valores con los operadores sobrecargados
resta = c1 - c2;
producto = c1 * c2;
cociente = c1 / c2;
// se imprimen los nmeros Complejos con el operador << sobrecargado
cout << c1 << ", " << c2 << ", " << c3 << ", " << c4 << endl;
cout << "Primer Complejo: " << c1 << endl;
cout << "Segundo Complejo: " << c2 << endl;
cout << "Suma: " << suma << endl;
cout << "Resta: " << resta << endl;
cout << "Producto: " << producto << endl;
cout << "Cociente: " << cociente << endl;
if (c1==c2)
cout << "Los Complejos son iguales." << endl;
else
cout << "Los Complejos no son iguales." << endl;
if (c1!=c2)
cout << "Los Complejos son diferentes." << endl;
else
cout << "Los Complejos no son diferentes." << endl;
cout << "Ya he terminado." << endl;
}
Lamentehumanaclasificalosconceptosdeacuerdoadosdimensiones:pertenencia
yvariedad.SepuededecirqueelFordFiestaesuntipodecoche(variedado,eningls,una
relacindeltipoisa)yqueunaruedaespartedeuncoche(pertenenciaounarelacindel
tipo has a). Antes de la llegada de la herencia, en C ya se haba resuelto el problema de la
pertenenciamediantelasestructuras,quepodansertodolocomplejasquesequisiera.Con
la herencia, como se va a ver en este captulo, se consigue clasificar los tipos de datos
(abstracciones)porvariedad,acercandoasunpasomslaprogramacinalmododerazonar
humano.
Comocasisiempre,C++havenidohaintentarsolucionar,loquelosprogramadores
porsucuentayasehabanprocuradomediantecomplejasestructurassobreC.As,mediante
unaprogramacincompleja,enlaqueentraaformarparteimportanteelpreprocesador,se
conseguan los conceptosde herenciatanto simple como mltiple, as como otros aspectos
de C++. Todos estos mecanismos, a veces ciertamente con apariencia de enrevesados, han
sidodesarrolladosrespondiendoanecesidadesdelaprogramacindealtonivel,porloque
enmuchoscasosintentaremoshacerhincapienlaaplicacindeloqueseexplica.
Como ya se ha mencionado, el mecanismo de la herencia es fuertemente
caractersticodelaprogramacinorientadaaobjetos.Porello,antesdecomenzaraahondar
enelconcepto,esimportantedestacarquenodejadeserunaherramientaquenospermitir
resolverconcomodidadyeleganciaciertosproblemas,peroqueensnoesunfindesdeel
punto de vista de la programacin. Uno de los mayores defectos que se dan a la hora de
realizarunprogramamediantePOO,esprecisamenteelabusodelmecanismodeherencia,y
la poca planificacin a la hora de definir nuestra estructura. Es bastante comn encontrar
desarrollosestancados,pocoeficientesopocousados,enC++debidoalacomplejidadypoca
planificacindelaestructuradelosobjetos.Porestemotivo,anahora,trasbastantesaos
condesarrollossobreC++,siguensaliendoyactualizndosedistintaslibrerascuyainterfacey
desarrollo siguen siendo en C, frente a otras anlogas y de mucho menor xito realizadas
sobreC++.
Por ello, hay que destacar lo siguiente: la herencia es un mecanismo de gran
potencia, pero que necesita de una fase de anlisis en profundidad previa a su
implementacin.Siesteanlisisnoserealizaadecuadamente,nosloperderemoseficiencia,
sinoqueelcdigoterminarcorrompidoyseranmsininteligiblequesobreC.
VeamosunejemplodeunaherenciasimplerealizadasobrecdigoC:
Seobservaenelejemplocmopodramosconsiderarapersonaclasebaseparalas
otras dos profesor y alumno. Mediante esta estructuracin, en determinadas funciones de
nuestro programa, podremos entender alumno o profesor como tales, o considerarlos slo
comopersonas(loquesignificara,accederalosprimeroscamposdelaestructura,loscuales
soncomunesaambostipos).
Enalgunoscasosunaclasenotieneotrautilidadqueladeserclasebaseparaotras
clases que se deriven de ella. A este tipo de clases base, de las que no se declara ningn
objeto,selesdenominaclasesbaseabstractas(ABC,AbstractBaseClass)ysufuncineslade
agruparmiembroscomunesdeotrasclasesquesederivarndeellas.Porejemplo,sepuede
definir la clase vehiculo para despus derivar de ella coche, bicicleta, patinete, etc., pero
todos los objetos que se declaren pertenecern a alguna de estas ltimas clases; no habr
vehculosqueseanslovehculos.
Las caractersticas comunes de estas clases (como una variable que indique si est
aradooenmarcha,otraqueindiquesuvelocidad,lafuncindearrancaryladefrenar,etc.),
pertenecernalaclasebaseylasqueseanparticularesdealgunadeellaspertenecernsloa
laclasederivada(porejemploelnmerodeplatosypiones,queslotienesentidoparauna
124 PROGRAMACIN C++ Y COMUNICACIONES.
bicicleta, o la funcin embragar que slo se aplicar a los vehculos de motor con varias
marchas).
Estemecanismodeherenciapresentamltiplesventajasevidentesaprimeravista,
como la posibilidad de reutilizar cdigo sin tener que escribirlo de nuevo. Esto es posible
porque todas las clases derivadas pueden utilizar el cdigo de la clase base sin tener que
volveradefinirloencadaunadeellas.
Tabla1:Herenciapblicayprivada.
Como ejemplo, se puede pensar en dos tipos de cuentas bancarias que comparten
algunas caractersticas y que tambin tienen algunas diferencias. Ambas cuentas tienen un
saldo,unintersyelnombredeltitulardelacuenta.Lacuentajovenesuntipodecuenta
querequierelaedaddelpropietario,mientrasquelacuentaempresarialnecesitaelnombre
delaempresa.ElproblemapodraresolverseestableciendounaclasebasellamadaC_Cuenta
ycreandodostiposdecuentaderivadosdedichaclasebase.
Paraindicarqueunaclasederivadeotraesnecesarioindicarloenladeclaracinde
la clase derivada, especificando el modo public o private en que deriva de su clase
base:
Ntese que algunas de las lneas han tenido que partirse en concreto los
constructores de las clases debido a su longitud. Esto es vlido y conveniente en C++,
intentandosiempremanteneralmximolaclaridaddelasdefiniciones.
#include <iostream.h>
class C_Cuenta
{
// Variables miembro
private:
char *Nombre; // Nombre de la persona
double Saldo; // Saldo Actual de la cuenta
double Interes; // Inters aplicado
public:
// Constructor
C_Cuenta(char *nombre, double saldo=0.0, double interes=0.0)
{
Nombre = new char[strlen(nombre)+1];
strcpy(Nombre, nombre);
SetSaldo(saldo);
SetInteres(interes);
126 PROGRAMACIN C++ Y COMUNICACIONES.
}
// Destructor
~Cuenta(){delete [] Nombre;}
// Mtodos
char *GetNombre(){ return Nombre; }
double GetSaldo(){ return Saldo; }
double GetInteres(){ return Interes; }
void SetSaldo(double saldo){ Saldo = saldo; }
void SetInteres(double interes){ Interes = interes; }
void Ingreso(double cantidad){SetSaldo(GetSaldo()+cantidad);}
friend ostream& operator<<(ostream& os, C_Cuenta& cuenta){
os << "Nombre=" << cuenta.GetNombre() << endl;
os << "Saldo=" << cuenta.GetSaldo() << endl;
return os;
}
};
//CuentaJoven deriva pblicamente de la clase Cuenta
class C_CuentaJoven : public C_Cuenta
{
private:
int Edad;
public:
C_CuentaJoven(char *nombre,int edad, double saldo=0.0,
double interes=0.0):C_Cuenta(nombre, saldo, interes) {
Edad = laEdad; //especifico de Cuenta Joven
}
};
class C_CuentaEmpresarial : public C_Cuenta
{
private:
char *NomEmpresa;
public:
C_CuentaEmpresarial(char *nombre, char *empresa,
double saldo=0.0, double interes=0.0)
:C_Cuenta(nombre, saldo, interes){
//especfico de Cuenta empresarial
NomEmpresa = new char[strlen(empresa)+1];
strcpy(NomEmpresa, empresa);
}
~C_CuentaEmpresarial(){delete [] NomEmpresa;}
};
void main()
{
C_CuentaJoven c1("Luis", 18, 10000.0, 1.0);
C_CuentaEmpresarial c2("Sara", "ELAI Ltd." ,100000.0);
void main(void)
{
decimal num(1,2);
128 PROGRAMACIN C++ Y COMUNICACIONES.
num.imprimir();
cout<<endl;
num.mostrar();
cout<<endl;
num.numero::imprimir();
}
Elresultadodeejecutaresteprogramaeselsiguiente:
1,2
1,2
1
Aunqueelejemplocarecedeutilidad,esciertamenteilustrativodecmosemaneja
eloperadorscope(::)cuandotenemosclasesderivadas.Seanimaallectoraanalizaraquien
hacen referencia los identificadores valor, e imprimir en cada caso. Ntese que para poder
escribirlafuncinmostrardelaclasedecimal,hasidonecesariodefinirvalorcomoprotected
enlaclasebase,yquelaherenciaespblica.Deestaforma,elvalornoesaccesibledesdeel
exterior,perosparalaclasederivada.
AntesdecontinuarconladescripcindeaspectosespecficosdelaherenciaenC++,
esnecesarioindicarquenotodoloquepertenecealaclasebaseesheredado.Loselementos
quenoseheredanson:
Constructores.
Destructores.
Funcionesfriend.
Funcionesydatosestticosdelaclase.
Operadordeasignacin(=)sobrecargado.
Los contructores y destructores tienen un tratamiento especfico como se ver a
continuacin.Aunquenoseheredansiqueseusanenelmomentodecrearseunainstancia
deunobjetoderivado.
Esteinicializadorbaseseespecificaponiendo,acontinuacindelosargumentosde
unconstructordelaclasederivada,elcarcterdospuntos(:)yelnombredelconstructorde
la clase o las clases base, seguido de una lista de argumentos entre parntesis. Estos
argumentos pueden ser funcin de los argumentos utilizados en el constructor de la clase
derivada.
Porejemplo,elconstructordelaclasedecimaltenaelsiguienteaspecto:
decimal(int val, int dec):numero(val){valor=dec;}
Con lo que se indica que la parte del objeto correspondiente a nmero, debe ser
inicializadoconelprimervalorpasadocomoargumentoenelconstructordelaclasedecimal.
Las listas de argumentos asociadas a las clases base pueden estar formadas por
constantes,variablesglobalesoporparmetrosquesepasanalafuncinconstructordela
clasederivada.
El inicializador base puede ser omitido en el caso de que la clase base tenga un
constructorpordefecto.Enelcasodequeelconstructordelaclasebaseexista,aldeclararun
objetodelaclasederivadaseejecutaprimeroelconstructordelaclasebase.
Deformaanlogaseoperarconeldestructor:eliminandoprimerolomsparticular
y despus lo general. Una funcin destructor de una clase derivada se ejecuta antes del
130 PROGRAMACIN C++ Y COMUNICACIONES.
Losconstructoressellamanenelordendederivacindelasclases.
Losdestructoressellamanenordeninverso.
Elsiguienteejemplointentailustrarestemododeproceder.
#include <iostream.h>
class Base
{
public:
Base() {cout << \nBase creada\n;}
~Base() {cout << Base destruida\n\n;}
}
void main()
{
D_clase1 d1;
D_clase2 d2;
Esteprogramagenerarlasiguientesalida:
Base creada
D_clase1 creada
Base creada
D_clase1 creada
D_clase2 creada
D_clase2 destruida
D_clase1 destruida
Base destruida
D_clase1 destruida
Base destruida
Herencia Simple: Todas las clases Herencia Mltiple: Las clases derivadas
derivadas tienen una nica clase base. tienen varias clases base.
Comoejemplosepuedepresentarelcasodequesetengaunaclaseparaelmanejo
delosdatosdelaempresa.SepodradefinirlaclaseC_CuentaEmpresarialcomolaherencia
mltiple de dos clases base: la ya bien conocida clase C_Cuenta y nueva clase llamada
C_Empresa,quesemuestraacontinuacin:
class C_Empresa
{
private:
char *NomEmpresa;
public:
C_Empresa(const char*laEmpresa)
{
NomEmpresa = new char[strlen(laEmpresa)+1];
strcpy(NomEmpresa, laEmpresa);
}
~C_Empresa(){ delete [] NomEmpresa; }
// Otros mtodos ...
};
Lasintaxisgeneralparaheredarunaclasedevariasclasesbasees:
class<c_derivada>:[public|private]<c_base_1>,[public|private]<base_2>,...
{
...
}
Lasclasesbaseseconstruyenenelordenenelqueaparecenenladeclaracindela
clasederivadadeizquierdaaderecha.Engeneral,cuandoseutilizaunalistadeclasesbase,
losconstructoressedebenllamarenordendeizquierdaaderecha.Losdestructoressedeben
llamarenordendederechaaizquierda.
Los inicializadotes base siguen esta misma sintaxis. Cuando es necesario utilizarlos,
se colocan tras la clase base separadospor comas. Tales el caso delejemplo de lacuenta
empresarialexpuestoanteriormente.
Hayquedestacarqueenposterioreslenguajesdesarrolladossiguiendolafilosofade
POO, la herencia mltiple se ha desechado por ser una posible fuente de errores. La razn
principalresideencmofinalmentevanaquedarordenadaslasestructurasdelosobjetosen
memoria.Sinembargo,aunquenoexisteestaherenciamltiple,podemosgenerarunaserie
declasesabstractasintermediasqueobtenganelmismoresultado,puestoqueelefectofinal
eselmismonoesmsqueunaagregacindedatosymtodos.
Laherenciamltiplepuedeademsproduciralgunosproblemas.Enocasionespuede
suceder que en las dos clases base existaunafuncin con el mismo nombre. Esto crea una
ambigedadcuandoseinvocaaunadeesasfunciones.
Veamosunejemplo:
#include <iostream.h>
class ClaseA {
public:
ClaseA() : valorA(10) {}
int LeerValor(){ return valorA; }
protected:
int valorA;
};
class ClaseB {
public:
ClaseB() : valorB(20) {}
int LeerValor(){ return valorB; }
protected:
int valorB;
};
class ClaseC : public ClaseA, public ClaseB {};
void main() {
ClaseC CC;
cout << CC.LeerValor() << endl;// error de compilacin
cout << CC.ClaseA::LeerValor() << endl;
cin.get();
}
Unasolucinpararesolverlaambigedadeslaquehemosadoptadoenelejemplo.
Pero existe otra, tambin podramos haber redefinido la funcin "LeerValor" en la clase
derivadademodoquesesuperpusiesealasfuncionesdelasclasesbase.
134 PROGRAMACIN C++ Y COMUNICACIONES.
#include <iostream.h>
class ClaseA
{
public:
ClaseA() : valorA(10) {}
int LeerValor(){ return valorA; }
protected:
int valorA;
};
class ClaseB
{
public:
ClaseB() : valorB(20) {}
int LeerValor(){ return valorB; }
protected:
int valorB;
};
class ClaseC : public ClaseA, public ClaseB
{
public:
int LeerValor(){return ClaseA::LeerValor();}
};
void main()
{
ClaseC CC;
cout << CC.LeerValor() << endl;
cin.get();
}
Clase A Clase A
Clase B Clase C
Clase D
LaClaseDheredardosveceslosdatosyfuncionesdelaClaseA,conlaconsiguiente
ambigedadalahoradeaccederadatosofuncionesheredadasdeClaseA.Parasolucionar
estoseusanlasclasesvirtuales.Cuandoderivemosunaclasepartiendodeunaovariasclases
base,podemoshacerquelasclasesbaseseanvirtuales.Estonoafectaralaclasederivada.
Formadedeclaracindeunaclasebasevirtual:
classMadre_1:virtual publicAbuela
...
}
Porejemplo:
class ClaseB : virtual public ClaseA {};
Ahora,laClaseDsloheredarunavezlaClaseA.Laestructuraquedaras:
136 PROGRAMACIN C++ Y COMUNICACIONES.
Clase A
Clase B Clase C
Clase D
Endefinitiva,unpunteroalaclasebasepuedealmacenarladireccindeunobjeto
pertenecienteaunaclasederivada.Sinembargo,seaplicarnlosmtodosdelaclaseala
que pertenezca el puntero, no los de la clase a la que pertenece el objeto. Por eso es
convenientehacerunaconversindinmicaforzada.
laclasebasecomoenladerivada.
Parapoderutilizarlaconversinforzadadurantelaejecucin,esnecesarioindicaral
compilador que se desea introducir informacin sobre las clases de los objetos en la
ejecucin.Paraello,enlaprcticaseindicacomohabilitarestemodo
Enelsiguienteejemplosepuedenverlasdistintasposibilidadesdeasignacinquese
puedenrealizarentreclasesbaseyclasesderivadaspormediodelasclasesCalseAyClaseB.
#include <iostream.h>
class ClaseA{
protected:
int a;
public:
ClaseA(int n):a(n){}
void mostrar(){cout<<a<<endl;}
};
class ClaseB:public ClaseA{
int b;
public:
ClaseB(int n, int m):ClaseA(n),b(m){}
void mostrar(){cout<<a<<,<<endl;};
} ;
void main()
{
ClaseA ca(2);
ClaseB cb(8,4);
ca.mostrar();
cb.mostrar();
//cb=ca; esto generara un error de compilacin (1)
ca=cb;
ca.mostrar();
138 PROGRAMACIN C++ Y COMUNICACIONES.
cb.mostrar();
ClaseA *c3=c1,*c4=c2;
c3->mostrar();
c4->mostrar();
ClaseB *c5;
c5 = static_cast<ClaseB *>(c3);
c5->mostrar(); //error en ejecucin (2)
c5 = static_cast<ClaseB *>(c4);
c5->mostrar();
delete c1;
delete c2;
}
En(1)seproduceunerrordecompilacinporquenosepermitelaasignacindesde
unobjetobaseaunobjetoderivadoporserelsegundomsextensoqueelprimero,porlo
quepartedelosatributosnosesabraquevalordebentomar.
Seobservasinembargoquelaasignacininversaesvlida.
En(2)semuestraunaconversinforzosadetipo.Seobligaalcompiladoraaceptar
queladireccinalmacenadaenc3esdeunobjetodeclaseB.Enestecasonoesas,porlo
que si por medio ce c5 ejecutamos un mtodo de la clase B, el resultado puede ser
desastroso,puestoquedichomtodoaccederaunazonadelamemoriaquenopertenece
al objeto y que incluso podra no pertenecer al programa con el consiguiente error del
sistemaoperativo.Hayquedestacarqueesteerrornoesdecompilacinsinodeejecucin.
Enlamayoriadeloscasos,silazonadememoriaaccedidaesnuestra,loquesemostrarser
el resultado de interpretar la memoria como si ah estuviera el atributo que estamos
consultando.
2,3
ExisteenC++laposibilidadderealizarunaconversindetiposquecompruebesiel
objetoapuntadoporunpunteroesonoasignableaunpunterodeunaclasederivada.Esta
conversindinmicaconsultaeltipodedatosdelobjetopresenteenlamemoriadurantela
ejecucin.Siestetipodedatosesconvertiblealtipoquetienequerecibirlo,entoncessehace
laconversin.Encasodenoseraselresultadodeestaconversinescero.
Para poder aplicar dynamic_cast, hayquetenerdosprecauciones. Enprimer lugar,
esta operacin solo puede aplicarse sobre tipos polimrficos. Como se ver en el captulo
siguiente,estoocurrecuandosetienequealgunodelosmtodosdelaclaseesvirtua.
Ensegundolugar,hayqueindicaralcompiladorquedebeincluirinformacinsobre
lostiposdeclaseenelcdigo.Estaopcindecompilacindeberindicarseenlasopciones
generalesdelcompiladorqueseestutilizando.
Dichoesto,elejemploquedaramsrobustoyelegantesiseescribelosiguiente.En
ladefinicindelaclaseClaseAincluiremosundestructorvirtualaadiendolasiguientelnea:
virtual ~ClaseA(){}
Yelfinaldelafuncinmainanteriorloreescribiremosdelaformasiguiente:
c5= dynamic_cast<ClaseB *>(c3);
if(c5!=NULL)c5->mostrar();
c5= dynamic_cast<ClaseB *>(c4);
if(c5!=NULL)c5->mostrar();
Enestecaso,sloserealizarlasegundaimpresin,puestoqueelsistemadetecta
queelobjetoapuntadoporc3esdetipoClaseA,yqueportantonoesunaasignacinvlida
la pretendida. Por el contrario, aunque c4 es un puntero de tipo ClaseA, la direccin que
contieneesdeunobjetodetipoClaseB,porloqueeloperadordetectadurantelaejecucin
quelaasignacinesvlida.
ElsiguienteprogramautilizalaclaseCCuentayadefinidaanteriormente:
void main()
{
CCuenta Cuenta1("Tu");
CCuenta Cuenta2("Yo",1000,10);
Cuenta1=Cuenta2; //(1)
CCuenta Cuenta3(Cuenta2); //(2)
CCuenta Cuenta4=Cuenta2; //(3)
}
En la lnea marcada con (1), claramente se utiliza el operador de asignacin
sobrecargado (si est definido). De igual forma, es claro que en la linea (2) se utiliza el
constructor de copia definido. Lo que es aparentemente una excepcin es la creacin de
Cuenta4enlalinea(3).Enestecaso,aunqueaparentementeparecequeseutilizaeloperador
deasignacin,sehaceusoimplcitodelconstructordecopia.
Una vez aclarado este aspectod ela sintaxis, vamos a ver de que modo se pueden
implementarestosdosmtodosnoheredadosenunaclasederivada:
#include <string.h>
#include <iostream.h>
class Nombre
{
char *nombre;
public:
Nombre(char *nom)
{
nombre=new char[strlen(nom)+1];
strcpy(nombre,nom);
}
Nombre(const Nombre &nom)
{
nombre=new char[strlen(nom.nombre)+1];
strcpy(nombre,nom.nombre);
}
Nombre &operator=(const Nombre &nom)
{
delete [] nombre;
nombre=new char[strlen(nom.nombre)+1];
strcpy(nombre,nom.nombre);
return *this;
}
~Nombre(){delete [] nombre;}
void mostrar(){cout<<nombre;}
};
class Alumno:public Nombre
{
int numero;
public:
Alumno(char *nom, int num):Nombre(nom),numero(num){}
Alumno(const Alumno &al):Nombre(al),numero(al.numero){};
Alumno &operator=(const Alumno &al)
{
Nombre::operator =(al);
numero=al.numero;
return *this;
}
};
void main()
{
Alumno uno("Juan Ramrez",43271);
Alumno dos=uno; //(1)
Alumno tres("Pepito",41278);
tres=dos; //(2)
Losmtodosqueseejecutanenlasinstruccionesmarcadassonlossiguientes:en(1)
seejecutaelconstructordecopiadeAlumno,peroantesdeejecutarseelcdigocontenido
entre las llaves se inicializa por medio del constructor de copia de Nombre, la parte
correspondienteaestaclasebase.PuestoqueunoesdeclaseAlumno,yestaesderivadade
nomre,laconversinesvidaeinmediata,talycomosemencionoenelanteriorapartado.
En(2)seutilizaeloperadordeasignacindelaclaseAlumno.Fjesequeenelcdigo
deesteoperador,sehaceunusoexplcitodeloperadordeasignacindeNombre.
4.7. Ejemplo
Elsiguienteejemploeselcdigoutilizadoenlasprcticasparalarealizacindeuna
pequeajerarquadeclasesquepermitelarealizacindeunapequeabiblioteca:
#include <iostream.h>
typedef std::string cadena;
class CFicha
{
protected:
cadena referencia;
cadena titulo;
public:
// Constructor
CFicha(cadena ref= "", cadena tit= "");
// Destructor
virtual ~CFicha() {};
// Otras funciones
void AsignarReferencia(cadena ref);
cadena ObtenerReferencia() ;
void AsignarTitulo(cadena tit);
cadena ObtenerTitulo() ;
void Imprimir();
void PedirFicha();
friend void TomarLinea(cadena&);
};
class CFichaLibro : public CFicha
{
private:
cadena autor;
cadena editorial;
public:
// Constructor
CFichaLibro(cadena ref= "", cadena tit= "", cadena aut=
"", cadena ed= "");
// Otras funciones
void AsignarAutor(cadena aut);
cadena ObtenerAutor();
void AsignarEditorial(cadena edit);
cadena ObtenerEditorial();
void PedirLibro();
void Imprimir();
};
class CFichaRevista : public CFicha
{
private:
int NroDeRevista;
int Anyo;
public:
// Constructor
CFichaRevista(cadena ref= "", cadena tit= "", int an= 0, int
nro= 0);
// Otras funciones
void AsignarNroDeRevista(int nro);
int ObtenerNroDeRevista() ;
void AsignarAnyo(int any);
int ObtenerAnyo() ;
void PedirRevista();
void Imprimir();
};
class CFichaVolumen : public CFichaLibro
{
private:
int NroDeVolumen;
public:
// Constructor
CFichaVolumen(cadena ref = "", cadena tit= "", cadena aut=
"", cadena edit= "", int Nro= 0);
// Otras funciones
void AsignarNroDeVolumen(int);
int ObtenerNroDeVolumen();
void PedirVolumen();
void Imprimir();
};
class CBiblioteca
{
private:
144 PROGRAMACIN C++ Y COMUNICACIONES.
/**************************************************************
Fin de las declaraciones comienzan las definiciones
**************************************************************/
cadena CFicha::ObtenerReferencia()
{
return referencia;
}
cadena CFicha::ObtenerTitulo()
{
return titulo;
}
void CFicha::PedirFicha()
{
cout << "Referencia.............: ";
TomarLinea(referencia);
cin.ignore(100, '\n');
cout << "Ttulo.................: ";
TomarLinea(titulo);
}
cadena CFichaLibro::ObtenerAutor()
{
return autor;
}
cadena CFichaLibro::ObtenerEditorial()
{
return editorial;
}
146 PROGRAMACIN C++ Y COMUNICACIONES.
void CFichaLibro::PedirLibro()
{
PedirFicha();
cout << "Autor..................: ";
TomarLinea(autor);
cout << "Editorial..............: ";
TomarLinea(editorial);
}
void CFichaLibro::Imprimir()
{
cout << "Autor: " << autor.data() <<endl;
cout << "Editorial: " << editorial.data() <<endl;
}
CFichaRevista::CFichaRevista(cadena ref, cadena tit, int
nroderev, int anyo) : CFicha(ref, tit), NroDeRevista(nroderev),
Anyo(anyo){}
int CFichaRevista::ObtenerNroDeRevista()
{
return NroDeRevista;
}
int CFichaRevista::ObtenerAnyo()
{
return Anyo;
}
void CFichaRevista::PedirRevista()
{
PedirFicha();
cout << "Nro. de la revista.....: ";
cin >> NroDeRevista;
cout << "Ao de publicacin.....: ";
cin >> Anyo;
}
void CFichaRevista::Imprimir()
{
cout << "Nro Revista: " << NroDeRevista <<endl;
int CFichaVolumen::ObtenerNroDeVolumen()
{
return NroDeVolumen;
}
void CFichaVolumen::PedirVolumen()
{
PedirLibro();
cout << "Nro. del volumen.......: ";
cin>>NroDeVolumen;
}
void CFichaVolumen::Imprimir()
{
cout << "Tomo: " << NroDeVolumen <<endl;
}
CBiblioteca::CBiblioteca(int n)
{
if (n < 0) n = 1;
ficha.reserve(n);
}
CBiblioteca::~CBiblioteca()
{
for (int i = 0; i < ficha.size(); i++)delete ficha[i];
}
// Indexacin
CFicha *CBiblioteca::operator[](int i)
{
if (i >= 0 && i < ficha.size()) return ficha[i];
else
{
cout << "error: ndice fuera de lmites\n";
return 0;
}
}
148 PROGRAMACIN C++ Y COMUNICACIONES.
int CBiblioteca::longitud()
{
//nos dice cuantos elementos se han introducido en el vector
return ficha.size();
}
cout<<"----------------------------------"<<endl;
}
/**********************************************************
************** MAIN ***********************************
**********************************************************/
void main()
{
150 PROGRAMACIN C++ Y COMUNICACIONES.
do
{
opcion = menu();
switch (opcion)
{
case 1: // aadir
cout << "Tipo de ficha < 1-(rev), 2-(lib), 3-(vol) >: ";
do
opcion = (int)leerDato();
while (opcion < 1 || opcion > 3);
unaFicha = leerDatos(opcion);
bibli.AnyadirFicha(unaFicha);
break;
case 2: // buscar
cout << "Ttulo total o parcial, o referencia: ";
TomarLinea(cadenabuscar);
pos = bibli.buscar(cadenabuscar, 0);
if (pos == -1)
{
if (bibli.longitud() != 0)
cout << "bsqueda fallida\n";
else
cout << "no hay fichas\n";
}
else
bibli.VisualizarFicha(pos);
break;
case 3: // buscar siguiente
pos = bibli.buscar(cadenabuscar, pos + 1);
if (pos == -1)
if (bibli.longitud() != 0)
cout << "bsqueda fallida\n";
else
cout << "no hay fichas\n";
else
bibli.VisualizarFicha(pos);
break;
case 4: // eliminar ficha
/*********************************************************
FUNCION: int menu()
ARGUMENTOS: ninguno
RETORNO: int. Devolver la opcin escogida (1-6)
DESCRIPCION: Imprime por pantalla el men principal y
solicita al usuario que seleccione. No retornar un
valor hasta que la seleccin sea vlida.
*********************************************************/
int menu()
{
cout << "\n\n";
cout << "1. Aadir ficha\n";
cout << "2. Buscar ficha\n";
cout << "3. Buscar siguiente\n";
cout << "4. Eliminar ficha\n";
cout << "5. Listado de la biblioteca\n";
cout << "6. Salir\n";
cout << endl;
cout << " Opcin: ";
int op;
do
op = (int)leerDato();
while (op < 1 || op > 6);
return op;
}
152 PROGRAMACIN C++ Y COMUNICACIONES.
/*********************************************************
FUNCION: CFicha *leerDatos(int op)
ARGUMENTOS:
int op: Indica el tipo de Ficha que se tiene que crear.
1= Revista, 2= Libro, 3=Volumen
RETORNO: CFicha *. Devolver un puntero a la ficha creada
dinmicamente en funcin de la seleccion y los valores
introducidos por el usuario.
DESCRIPCION: Funcion principal que es llamada cada vez que
quiera crear una ficha de cualquire tipo.
*********************************************************/
CFicha *leerDatos(int op)
{
CFicha *obj=NULL;
switch(op)
{
case 1:
{
CFichaRevista *aux = new CFichaRevista();
aux->PedirRevista();
obj=aux;
}
break;
case 2:
{
CFichaLibro *aux = new CFichaLibro();
aux->PedirLibro();
obj=aux;
}
break;
case 3:
{
CFichaVolumen *aux = new CFichaVolumen();
aux->PedirVolumen();
obj=aux;
}
}
return obj;
}
/*********************************************************
FUNCION: int leerDatos()
ARGUMENTOS: ninguno
RETORNO: int. Retorna el nmero leido
DESCRIPCION: Funcion especial para hacer ms cmoda y
segura la lectura de nmeros del teclado.
*********************************************************/
int leerDato()
{
int dato = 0;
cin >> dato;
while (cin.fail()) // si el dato es incorrecto, limpiar el
{ // bfer y volverlo a leer
cout << '\a';
cin.clear();
cin.ignore(100, '\n');
cin >> dato;
}
// Eliminar posibles caracteres sobrantes
cin.clear();
cin.ignore(100, '\n');
return dato;
}
5. El Polimorfismo
Conestecaptulosetendrnlasherramientasbsicasparaeldesarrollodeunbuen
programa en C++. An quedara el uso de plantillas, pero estas pueden ser sustituidas en
muchos casos por el polimorfismo, y desde luego son ms difciles de utilizar por un
programadornovelquelosmecanismoshastaahoraexplicados.
Antes de adentrarse en el concepto depolimorfismo, su utilidad y su casustica, es
necesarioaclararalgnconceptoenloqueserefierealasuperposicinylasobrecarga:
Talycomosevienelcaptuloanteriorenunaclasederivadasepuededefiniruna
funcinqueyaexistaenlaclasebase.Estoseconocecomo"overriding",osuperposicinde
unafuncin.Ladefinicindelafuncinenlaclasederivadaocultaladefinicinpreviaenla
clasebase.Encasonecesario,esposibleaccederalafuncinocultadelaclasebasemediante
sunombrecompleto:
<objeto>.<clase_base>::<mtodo>;
Cuando se superpone una funcin, se ocultan todas las funciones con el mismo
nombre en la clase base. Supongamos que hemos sobrecargado la funcin de la clase base
quedespusvolveremosadefinirenlaclasederivada:
#include <iostream.h>
class ClaseA
{
public:
void Incrementar() { cout << "Suma 1" << endl; }
void Incrementar(int n) { cout << "Suma " << n << endl; }
};
class ClaseB : public ClaseA
{
public:
void Incrementar() { cout << "Suma 2" << endl; }
};
int main()
{
ClaseB objeto;
objeto.Incrementar();
objeto.Incrementar(10); //Existe este mtodo?
objeto.ClaseA::Incrementar();
objeto.ClaseA::Incrementar(10);
cin.get();
return 0;
}
Ahora bien, no es posible acceder a ninguna de las funciones superpuestas de la
clase base, aunque tengan distintos valores de retorno o distinto nmero o tipo de
parmetros.Todaslasfunciones"incrementar"delaclasebasehanquedadoocultas,yslo
son accesibles mediante el nombre completo. Por ello la lnea marcada dar un error de
compilacin, puesto que no existe la funcin incrementar definida en la claseB que reciba
comoargumentountipodedatosalque10seaconvertible.
Trascorregirelerroreliminandoestalnea,lasalidaser:
Suma 2
156 PROGRAMACIN C++ Y COMUNICACIONES.
Suma 1
Suma 10
5.2. Polimorfismo
Ha llegado el momento de introducir uno de los conceptos ms importantes de la
programacinorientadaaobjetos:elpolimorfismo.
En lo que concierne a clases, el polimorfismo en C++, llega a su mxima expresin
cuandolasusamosjuntoconpunterosoconreferencias.Comosehavisto,C++nospermite
accederaobjetosdeunaclasederivadausandounpunteroalaclasebase.Enesoconsisteo
sebasaelpolimorfismo.Hataahoraslopodemosaccederadatosyfuncionesqueexistanen
la clase base, los datos y funciones propias de los objetos de clases derivadas sern
inaccesibles. Esto es debido a que el compilador decide en tiempo de compilacin que
mtodosyatributosestndisponiblesenfuncindelcontenedor.
Parailustrarlovamosaverunejemplosobreunaestructuradeclasesbasadoenla
clase"Persona"ydosclasesderivadas"Empleado"y"Estudiante":
#include <iostream.h>
#include <string.h>
class Persona
{
public:
Persona(char *n) { strcpy(nombre, n); }
void VerNombre() { cout << nombre << endl; }
protected:
char nombre[30];
};
class Empleado : public Persona
{
public:
Empleado(char *n) : Persona(n) {}
void VerNombre()
{
cout << "Emp: " << nombre << endl;
}
};
void VerNombre()
{
cout << "Est: " << nombre << endl;
}
};
void main() {
Persona *Pepito = new Estudiante("Jose");
Persona *Carlos = new Empleado("Carlos");
Carlos->VerNombre();
Pepito->VerNombre();
delete Pepito;
delete Carlos;
}
Carlos
Jose
Podemos comprobar que se ejecuta la versin de la funcin "VerNombre" que
hemos definido para la clase base, y no la de las clases derivadas. Esto es debido a que la
funcinqueseejecutaseresuelveentiempodeEJECUCIONatendiendonoaltipodeobjeto
apuntado,sinoaltipodelapuntador.
Poreso,siescribimos:
Estudiante *Pepito=new Estudiante(Jose);
Empleado *Carlos=new Empleado(Carlos);
EntoncessiqueseejecutarelmtodoVerNombresuperpuesto.
Esto mismo sucede con las referencias. Las siguientes lneas de cdigo son
totalmentevlidas,siendoelefectoanlogoalobtenidopormediodepunteros:
Estudiante Jose(Jose);
Persona &pJose=Jose;
pJose.VerNombre();
Esdecir,enestecaso,atendiendoalrecipienteynoaloapuntado,seutilizarde
nuevoelmtodoVerNombredelaclasePersona,apesardequerealmentepJoseesunalias
158 PROGRAMACIN C++ Y COMUNICACIONES.
deunobjetodetipoEstudiante.Yaobservamosqueunobjetosecomportadedistintaforma
enfuncindeconqueseloreferencieoapunte.
Sin embargo, parece interesante que cada objeto se comporte como debe
independientementedelrecipiente,esdecir,independientementedeconquesereferencieo
apunteestonosllevaalconceptodepolimorfismodelamanodelosdenominadosmtodos
virtuales.
Mtodos virtuales
Unmtodovirtualesunmtododeunaclasebasequepuedeserredefinidoencada
unadelasclasesderivadasdeesta,yqueunavezredefinidopuedeseraccedidopormedio
deunpunteroounareferenciaalaclasebase,resolvindoseentonceslallamadaenfuncin
delobjetoreferidoenvezdeenfuncindeconqusehacelareferencia.
Quevieneasignificarquesienunaclasebasedefinimosunmtodocomovirtual,si
estemtodoessuperpuestoporunaclasederivada,alinvocarloutilizandounpunteroouna
referenciadelaclasebase,seejecutarelmtododelaclasederivada!.
Cuandounaclasetienealgnmtodovirtualbiendirectamente,bienporherencia
sedicequedichaclaseespolimrfica.
Paradeclararunmtodocomovirtualseutilizalasiguientesintaxis:
virtual <tipo> <nombre_funcin>(<lista_parmetros>) [{}];
Est:Jose
Ahora,alllamaraPepito>VerNombre()seinvocaalafuncinVerNombredelaclase
Estudiante,yalllamaraCarlos>VerNombre()seinvocaalafuncindelaclaseEmpleado,a
pesardequetantoPepitocomoCarlossonpunterosalaclasePersona.
Deigualformaocurrirsienvezdeutilizarpunteros,hacemosusodereferencias:
void main()
{
Estudiante Pepito("Jose");
Empleado Carlos("Carlos");
Persona &rPepito = Pepito; // Referencia como Persona
Persona &rCarlos = Carlos; // Referencia como Persona
rCarlos.VerNombre(); //cada objeto ejecuta su mtodo
rPepito.VerNombre(); //en vez de utilizar el de Persona
}
Portanto,laideacentraldelpolimorfismoesladepoderllamarafuncionesdistintas
aunque tengan el mismo nombre, segn la clase a la que pertenece el objeto al que se
aplican. Esto es imposible utilizando nombres de objetos: siempre se aplica la funcin
miembro de la clase correspondiente al nombre del objeto, y esto se decide en tiempo de
compilacin.
Sinembargo,utilizandopunterospuedeconseguirseelobjetivobuscado.Recurdese
que un puntero a la clase base puede contener direcciones de objetos de cualquierade las
clasesderivadas.
Una vez que una funcin es declarada como virtual, lo seguir siendo en las
clasesderivadas,esdecir,lapropiedadvirtualsehereda.
siendo pblica en la clase base, pudiendo por tanto ejecutarse ese mtodo
privadodesdefuerapormediodeunpunteroalaclasebase.
Una llamada a un mtodo virtual se resuelve siempre en funcin del tipo del
objetoreferenciado.
Unallamadaaunmtodonormalseresuelvesiempreenfuncindeltipodela
referenciaopunteroutilizado.
Porsumododefuncionamientointerno(esdecir,porelmodoenquerealmente
trabajaelordenador)lasfuncionesvirtualessonunpocomenoseficientesque
lasfuncionesnormales.
Vamos a ver algn ejemplo adicional que ayude a entender el polimorfismo y las
clasespolimrficas.
#include <iostream.h>
class Base
{
public:
virtual void ident(){cout<<"Base"<<endl;}
};
class Derivada1:public Base
{
public:
void ident(){cout<<"Primera derivada"<<endl;}
};
class Derivada2:public Base
{
public:
void ident(){cout<<"Segunda derivada"<<endl;}
};
class Derivada3:public Base
{
public:
void ident(){cout<<"Tercera derivada"<<endl;}
};
void main()
{
Base base,*pbase;
Derivada1 primera;
Derivada2 segunda;
Derivada3 tercera;
pbase=&base;
pbase->ident();
pbase=&primera;
pbase->ident();
pbase=&segunda;
pbase->ident();
pbase=&tercera;
pbase->ident();
}
Evidentemente,elresultadodeejecutarestecdigoeselsiguiente:
Base
Primera derivada
Segunda derivada
Tercera derivada
nuevo cuatro veces Base. Esto es debido a que desde el punto de vista del puntero que
contenedor (de tipo Base) la funcin ya no es virtual y por tanto se decide en tiempo de
compilacincomocualquiermtodonormal.Parapoderaccederalmtododefinidoporlas
clasesderivadasalmenossernecesarioqueutilicemosunpunterodetipoDerivada2para
aquellasclasesquesonpolimrficas(enestecasosloloseraDerivada3).
Porltimo,sivolvemosalprogramaoriginal,yestablecemosqueelmtodoidentes
privado en la clase Derivada2, se observa que no afecta para nada al funcionamiento de
nuestroprograma.
El polimorfismo hace posible que un usuario pueda aadir nuevas clases a una
jerarquasinmodificarorecompilarelcdigooriginal.Estoquieredecirquesideseaaadir
una nueva clase derivada es suficiente con establecer la clase de la que deriva, definir sus
nuevas variables y funciones miembro, y compilar esta parte del cdigo, ensamblndolo
despusconloqueyaestabacompiladopreviamente.
Elsiguienteejemploesunpocomslargoycomplicadorespectodelosanteriores,
peroesmselocuenteantelasposibilidadesquenosofreceelpolimorfismo:
#include <iostream.h>
class Vehiculo
{
public:
virtual void muestra(ostream &co){}
virtual void rellena(){}
friend ostream& operator <<(ostream &co,Vehiculo &ve)
{
ve.muestra(co);
return co;
}
};
class Coche:public Vehiculo
{
protected:
char marca[20];
char modelo[20];
public:
void muestra(ostream &co)
{
co<<"Coche marca "<<marca<<" modelo "<<modelo<<endl;
}
void rellena()
{
cout<<"Marca?:";
cin>>marca;
cout<<"Modelo?:";
cin>>modelo;
cin.clear();
}
};
class Camion:public Coche
{
private:
int carga;
public:
void muestra(ostream &co)
{
co<<"Camion marca "<<marca<<" modelo "<<modelo<<endl;
co<<"\tCapacidad de carga: "<<carga<< "Kg."<<endl;
}
void rellena()
{
Coche::rellena();
cout<<"Carga mxima?:";
cin>>carga;
cin.clear();
}
};
void main()
{
Vehiculo *flota[4];
int seleccion=0;
for(int i=0;i<3;i++)
{
cout<<"Seleccione tipo del vehiculo "<<i<<":\n";
cout<<"(1-Camin, 2-Coche): ";
while((seleccion<1)||(seleccion>2))
cin>>seleccion;
switch(seleccion)
{
case 1: flota[i]=new Camion;break;
case 2: flota[i]=new Coche;break;
}
seleccion=0;
flota[i]->rellena();
}
cout<<"\n Estos son los vehiculos introducidos:\n";
for(i=0;i<3;i++)cout<<i<<":"<<*flota[i];
164 PROGRAMACIN C++ Y COMUNICACIONES.
}
Unejemplodeejecucindeesteprogramaeselsiguiente:
Seleccione tipo del vehiculo 0:
(1-Camin, 2-Coche): 1
Marca?:SCANIA
Modelo?:SuperTruck
Carga mxima?:22000
Seleccione tipo del vehiculo 1:
(1-Camin, 2-Coche): 2
Marca?:Seat
Modelo?:Ibiza
Seleccione tipo del vehiculo 2:
(1-Camin, 2-Coche): 2
Marca?:Renault
Modelo?:Twingo
Se observa entonces como es posible almacenar y tratar los objetos como iguales
atendiendoaqueheredandeunamismaclasebase,ysinembargo,estosmismosobjetosson
capaces de realizar acciones distintas o especializadas cuando se ejecutan sus mtodos
virtuales.Estoeslapotenciadelpolimorfismo,ytalvezgraciasalmismoalgunocomienzea
vislumbrarelporqueseparecentantoyalavezsondistintoslosprogramasquesemanejan
sobreWindows.
decirquebuscarprimeroenlapropiaclase,luegoenlaclaseanteriorenelordenjerrquico
yseirsubiendoeneseordenhastadarconunaclasequetengadefinidalafuncinbuscada.
Cadaobjetocreadodeunaclasequetengaunafuncinvirtualcontieneunpuntero
ocultoalavtabledesuclase.Medianteesepunteroaccedeasuvtablecorrespondienteya
travsdeestatablaaccedealadefinicinadecuadadelafuncinvirtual.Esestetrabajoextra
elquehacequelasfuncionesvirtualesseanmenoseficientesquelasfuncionesnormales.
Pepito->VerNombre();
Gente[0] = Carlos->Clonar();
Gente[0]->VerNombre();
Gente[1] = Pepito->Clonar();
Gente[1]->VerNombre();
delete Pepito;
delete Carlos;
delete Gente[0];
delete Gente[1];
cin.get();
return 0;
}
Hemosdefinidoelconstructorcopiaparaquesepuedavercuandoesinvocado.La
salidaessta:
Emp: Carlos
Est: Jose
Per: constructor copia.
Emp: constructor copia.
Emp: Carlos
Per: constructor copia.
Est: constructor copia.
Est: Jose
Estemtodoaseguraquesiempresellamaalconstructorcopiaadecuado,yaquese
hacedesdeunafuncinvirtual.
Siunconstructorllamaaunafuncinvirtual,stasersiempreladelaclasebase.
Estoesdebidoaqueelobjetodelaclasederivadaannohasidocreada.
Aldefinirunafuncincomovirtualpurahayquetenerencuentaque:
Nohacefaltadefinirelcdigodeesafuncinenlaclasebase.
Nosepuedendefinirobjetosdelaclasebase,yaquenosepuedellamaralas
funcionesvirtualespuras.
Aparentementepuedeparecerquecarecedesentidodefinirunaclasedelaqueno
vaaexistirningnobjeto,perosepuedeafirmar,sinmiedoaequivocarse,quelaabstraccin
esunaherramientaimprescindibleparauncorrectodiseodelaProgramacinOrientadaa
Objetos.
Habitualmente las clases superiores de muchas jerarquas de clases son clases
abstractas y las clases que heredan de ellas definen sus propias funciones virtuales,
convirtindoseasenfuncionesconcretas.
No es posible crear objetos de una clase abstracta, estas clases slo se usan como
clasesbaseparaladeclaracindeclasesderivadas.
Las funciones virtuales puras sern aquellas que siempre se definirn en las clases
derivadas,demodoquenosernecesariodefinirlasenlaclasebase.
Noestpermitidocrearobjetosdeunaclaseabstracta.
Siemprehayquedefinirtodaslasfuncionesvirtualesdeunaclaseabstractaen
sus clases derivadas, no hacerlo as implica que la nueva clase derivada ser
tambinabstracta.
Para crear un ejemplo de clases abstractas, recurriremos de nuevo a nuestra clase
"Persona". Haremos que sta clase sea abstracta. De hecho, en nuestros programas de
ejemplonuncahemosdeclaradounobjeto"Persona".
Veamosunejemplo:
#include <iostream>
#include <cstring>
using namespace std;
class Persona {
public:
Persona(char *n) { strcpy(nombre, n); }
virtual void Mostrar() = 0;
protected:
char nombre[30];
};
class Empleado : public Persona {
public:
Empleado(char *n, int s) : Persona(n), salario(s) {}
void Mostrar() const;
int LeeSalario() const { return salario; }
void ModificaSalario(int s) { salario = s; }
protected:
int salario;
};
void Empleado::Mostrar() const {
cout << "Empleado: " << nombre
<< ", Salario: " << salario
<< endl;
}
class Estudiante : public Persona {
public:
Estudiante(char *n, float no) : Persona(n), nota(no) {}
void Mostrar() const;
float LeeNota() const { return nota; }
170 PROGRAMACIN C++ Y COMUNICACIONES.
Lasalidaseras:
Enesteejemplocombinamoselusodefuncionesvirtualespurasconpolimorfismo.
Fjate que, aunque hayamos declarado los objetos "Pepito" y "Pablito" de tipo puntero a
"Persona" (1), en realidad no creamos objetos de ese tipo, sino de los tipos "Empleado" y
"Estudiante".
5.5. Ejemplos
Enlacuenta_joven,noseabonarelinterspactadosielsaldoesinferiora
unlmite.
Sielsaldoesmenorque50000,seaplicaelintersestablecidopreviamente.
Elcdigocorrespondientequedaradelasiguienteforma:
class C_Cuenta {
// Variables miembro
private:
double Saldo; // Saldo Actual de la cuenta
double Interes; // Inters calculado hasta el momento, anual,
// en tanto por ciento %
public:
//Constructor
C_Cuenta(double unSaldo=0.0, double unInteres=4.0)
{
SetSaldo(unSaldo);
SetInteres(unInteres);
}
// Acciones Bsicas
inline double GetSaldo()
{ return Saldo; }
inline double GetInteres()
{ return Interes; }
inline void SetSaldo(double unSaldo)
{ Saldo = unSaldo; }
inline void SetInteres(double unInteres)
{ Interes = unInteres; }
void Ingreso(double unaCantidad)
{ SetSaldo( GetSaldo() + unaCantidad ); }
virtual void AbonaInteresMensual()
{
SetSaldo( GetSaldo() * ( 1.0 + GetInteres() / 12.0 / 100.0) );
}
// etc...
};
6. Plantillas
La generalidad es una propiedad que permite definir una clase o una funcin sin
tener que especificar el tipo de todos o alguno de sus miembros. Esta propiedad no es
imprescindible en un lenguaje de programacin orientado a objetos y ni siquiera es una de
sus caractersticas. Esta caracterstica del C++ apareci mucho ms tarde que el resto del
lenguaje, al final de la dcada de los ochenta. Esta generalidad se alcanza con las plantillas
(templates).
Lautilidadprincipaldeestetipodeclasesofuncionesesladeagruparvariablescuyo
tipo no est predeterminado. As el funcionamiento de una pila, una cola, una lista, un
conjunto,undiccionarioounarrayeselmismoindependientementedeltipodedatosque
almacene(int,long,double,char,uobjetosdeunaclasedefinidaporelusuario).Endefinitiva
estasclasessedefinenindependientementedeltipodevariablesquevayanaconteneryesel
usuario de la clase el que debe indicar ese tipo en el momento de crear un objeto de esa
clase.
6.1. Introduccin
Hemosindicadoqueenlaprogramacinclsicaexistaunaclaradiferenciacinentre
los datos y su manipulacin, es decir, entre los datos y el conjunto de algoritmos para
manejarlos. Los datos eran tipos muy simples, y generalmente los algoritmos estaban
agrupadosenfuncionesorientadasdeformamuyespecficaalosdatosquedebanmanejar.
Posteriormente la POO introdujo nuevas facilidades: La posibilidad de extender el
conceptodedato,permitiendoqueexistiesentiposmsComplejosalosquesepodaasociar
laoperatorianecesaria.Estanuevahabilidadfueperfiladaconunpardemejorasadicionales:
Laposibilidaddeocultacindedeterminadosdetallesinternos,irrelevantesparaelusuario,y
lacapacidaddeherenciasimpleomltiple.
Observe que las mejoras introducidas por la POO se pueden sintetizar en tres
palabras:Composicin,ocultacinyherencia.Deotrolado,laposibilidaddeincluirjuntos
los datos y su operatoria no era exactamente novedosa. Esta circunstancia ya exista de
formasubyacenteentodosloslenguajes.Recuerdequeelconceptodeentero(intenC)ya
incluyeimplcitamentetodounlgebrayreglasdeusoparadichotipo.Observetambinque
laPOOmantieneunparadigmadeprogramacinorientadoaldato(oestructurasdedatos).
De hecho los "Objetos" se definen como instancias concretas de las clases, y estas
representan nuevos tiposdedatos, de modo que POO es sinnimo de Programacin
OrientadaaTiposdedatos
Laprogramacinorientadaaldatorazonadelsiguientemodo:Representemos
untipodedatogenrico(porejemploint)quepermitarepresentarobjetoscon
ciertas caractersticas comunes (peras y manzanas por ejemplo). Definamos
tambinqueoperacionespuedenaplicarseaestetipo(porejemploaritmticas)
y sus reglas de uso, independientemente que el tipo represente peras o
manzanasencadacaso.
Yasetratedeclasesofunciones,laposibilidaddeutilizaruntipocomoparmetroen
ladefinicin,posibilitalaexistenciadeentesdeniveldeabstraccinsuperioraldefuncino
claseconcreta.Podramosdecirquesetratadefuncionesoclasesgenricas;parametrizadas
(deahsunombre).Las"instancias"concretasdeestasclasesyfuncionesconformanfamilias
de funciones o clases relacionadas por un cierto "denominador comn", de forma que
Plantilladeclase(templateclass)osuequivalente:clasegenrica.
Plantilladefuncin(templatefunction)osuequivalente:funcingenrica.
Definida una plantilla, al proceso por el cual se obtienen clases especializadas (es
decirparaalgunodelostiposdedatosespecficos)sedenominainstanciacinodelaplantilla
o especializacin de una clase o mtodo genrico. A las funciones y clases generadas para
determinadostiposdedatosselasdenominaentoncescomoclasesofuncionesconcretaso
especializadas.
Comosehaindicado,lasplantillasrepresentanunadelasltimasimplementaciones
del lenguaje y constituyen una de las soluciones adoptadas por C++ para dar soporte a la
programacin genrica. Aunque inicialmente fueron introducidas para dar soporte a las
tcnicas que se necesitaban para la Librera Estndar (para lo que se mostraron muy
adecuadas),sontambinoportunasparamuchassituacionesdeprogramacin.Precisamente
la exigencia fundamental de diseo de la citada librera era lograr algoritmos con el mayor
grado de abstraccin posible, de forma que pudieran adaptarse al mayor nmero de
situacionesconcretas.
178 PROGRAMACIN C++ Y COMUNICACIONES.
Eltiempoparecedemostrarquesusautoresrealizaronunmagnficotrabajoqueva
ms all de la potencia, capacidad y versatilidad de la Librera Estndar C++ y de que otros
lenguajeshayan seguido la senda marcada por C++ en este sentido. Tal es el casode Java,
con su JGL ("Java Generic Library"). Lo que comenz como una herramienta para la
generacin parametrizada de nuevos tipos de datos (clases), se ha convertido por propio
derechoenunnuevoparadigma,lametaprogramacin(programasqueescribenprogramas).
De lo dicho hasta ahora puede deducirse, que las funciones y clases obtenidas a
partir de versiones genricas (plantillas), pueden obtenerse tambin mediante codificacin
manual (en realidad no se diferencian en nada de estas ltimas). Aunque en lo tocante a
eficaciaytamaodelcdigo,lasprimeraspuedancompetirenigualdaddecondicionescon
lasobtenidasmanualmente.Esto seconsigueporqueelusodeplantillasnoimplicaningn
mecanismo de tiempo de ejecucin. Las plantillas dependen exclusivamente de las
propiedades de los tipos que utiliza como parmetros y todo se resuelve en tiempo de
compilacin. Podramos pensar que su resolucin es similar a las macros de C en el que se
hacaunasustitucintextualdelaexpresinindicadaeneldefineporlaexpresinpuestaa
continuacin,peroenfuncindeunosparmetros.Deigualforma,cuandoseespecializauna
plantilla,seescribeelcdigoconlostipossustitudosporloindicadoenlaplantilla,ydespus
seprocedeacompilartantoelcdigoescritomanualmentecomoelescritoautomticamente
porestemecanismo.
Lasplantillasrepresentanunmtodomuyeficazdegenerarcdigo(definicionesde
funciones y clases) a partir de definiciones relativamente pequeas. Adems su utilizacin
permitetcnicasdeprogramacinavanzadas,enlasqueimplementacionesmuysofisticadas
semuestranmedianteinterfacesqueocultanalusuariolacomplejidad,mostrndolasoloen
la medida en que necesite hacer uso de ella. De hecho, cada una de las potentes
abstraccionesqueseutilizanenlaLibreraEstndarestrepresentadacomounaplantilla.A
excepcin de algunas pocas funciones, prcticamente el 100% de la Librera Estndar est
relacionada con las plantillas, de ah que hasta ahora nose halla hecho mucha referenciaa
estalibrerapertenecientealestndardeC++.
Lapalabraclavetemplate
C++utilizaunapalabraclaveespecficatemplateparadeclararydefinirfuncionesy
clases genricas. En estos casos acta como un especificador de tipo y va unido al par de
ngulos<>quedelimitanlosargumentosdelaplantilla:
template <T> void fun(T& ref); // funcin genrica
template <T> class C {/*...*/}; // clase genrica
Enalgunasotras(raras)ocasioneslapalabratemplateseutilizacomocalificadorpara
indicar que determinada entidad es una plantilla (y en consecuencia puede aceptar
argumentos)cuandoelcompiladornopuedededucirloporsmismo.
Bien,puesunavezexpuestaslasideasprincipalesreferentesalconceptodeplantilla,
vamos a ver en primer lugar como se realzan funciones genricas, para despus explicar el
conceptoyelmododefuncionamientodelasclasesgenricas.
El problema que presenta C++ para esta propuesta es que al ser un lenguaje
fuertementetipado,ladeclaracincmax(a,b)requiereespecificareltipodeargumentosy
valordevuelto.Enrealidadserequierealgoas:
tipoTmax(tipoTa,tipoTb);
y la sintaxis del lenguaje no permite que tipoT sea algo variable. Una posible
solucin es sobrecargar la funcin max(), definiendo tantas versiones como tipos distintos
debamosutilizar.
double max(double a,double b){return a>b?a:b;}
int max(int a,int b){return a>b?a:b;}
Otraalternativaserautilizarunamacro:
#define max(a, b) ((a > b) ? a : b)
peroestopresentasusinconvenientes.Empezandoporquesuutilizacinpermitira
comparar un entero con una estructura o una matriz, algo que est claramente fuera del
propsitodelafuncinquepretendemos.
La solucin al problema enunciado es utilizar una funcin genrica (plantilla). La
sintaxisdesudefinicineslasiguiente:
template <class T> T max(T a, T b)
{
return (a > b) ? a : b;
}
180 PROGRAMACIN C++ Y COMUNICACIONES.
<classT>eslalistadeparmetros.Representael/losparametrosdelaplantilla.Los
parmetrosdeunaplantillafuncionaenciertaformacomolosargumentosdeunamacro(el
trabajodeestamacroesgenerarcdigodefunciones).Esimportantesignificarqueutilizamos
dosconceptosdistintos(aunquerelacionados):losparmetrosdelaplantilla(contenidosen
la lista template <....> ) y los argumentos de la funcin (argumentos con que se invoca la
funcinencadacasoconcreto).
Lomismoqueenlasfuncionesexplcitas,lasgenricaspuedenserdeclaradasantes
desuutilizacin:
template <class T> T max(T, T);
ydefinidasdespus:
template <class T> T max(T a, T b)
{
return (a > b) ? a : b;
}
En(1)losargumentosdelafuncinsondosobjetostipoint;mientrasen(2)sondos
objetos tipo UnaClase. El compilador es capaz de construir dos funciones aplicando los
parmetrosadecuadosalaplantilla.Enelprimercaso,elparmetroesunint;enelsegundo
un tipo UnaClase. Como veremos ms adelante, es de la mxima importancia que el
compilador sea capaz de deducir los parmetros de la plantilla a partir de los argumentos
actuales (los utilizados en cada invocacin de la funcin), as como las medidas sintcticas
adoptadascuandoestonoesposibleporproducirseambigedad.
Unafuncingenricapuedetenermsargumentosquelaplantilla.Porejemplo:
template <class T> void func(T, inf, char, long, ...);
Tambinpuedetenermenos:
template <class T> void func();
La forma de operar en este caso para que el compilador deduzca el parmetro
correcto T a utilizar en la plantilla, se muestra ms adelante cuando se hable de la
especificacinexplcitadelosargumentosdeunaplantilla.
Llegadosaestepuntoesconvenientehaceralgunasobservacionesimportantes:
Las funciones genricas son entes de nivel de abstraccin superior a las funciones
concretas (en este contexto preferimos llamarlas funciones explcitas), pero las funciones
genricassolotienenexistenciaenelcdigofuenteyenlamentedelprogramador.Hemos
dichoqueelmecanismodeplantillasC++seresuelveentiempodecompilacin,demodoque
enelejecutable,ydurantelaejecucin,noexistenadaparecidoaunafuncingenrica,solo
existenespecializaciones(instanciasdelafuncingenrica).
Ocurrequesiestainstanciaaparecemsdeunavezenunmdulo,oesgenerada
enmsdeunmdulo,elenlazadorlasrefundeautomticamenteenunasoladefinicin,de
formaquesoloexistaunacopiadecadainstancia.Dichoenotraspalabras:enlaaplicacin
resultante solo existir una definicin de cada funcin. Por contra, si no existe ninguna
invocacinnosegeneraningncdigo.
Aunque la utilizacin de funciones genricas conduce a un cdigo elegante y
reducido,quenosecorrespondeconelresultadofinalenelejecutable.Silaaplicacinutiliza
muchasplantillasconmuchostiposdiferentes,elresultadoeslageneracindegrancantidad
decdigoconelconsiguienteconsumodeespacio.Estacrecimientodelcdigoesconocida
como "Code bloat", y puede llegar a ser un problema. En especial cuando se utilizan las
plantillas de la Librera Estndar, aunque existen ciertas tcnicas para evitarlo. Como regla
182 PROGRAMACIN C++ Y COMUNICACIONES.
general,lasaplicacionesquehaceusoextensivodeplantillasresultangrandesconsumidoras
dememoria(eselcostodelacomodidad).
Puesto que cada instancia de una funcin genrica es una verdadera funcin, cada
especializacindisponedesupropiacopiadelasvariablesestticaslocalesquehubiese.Se
les pueden declarar punteros y en general gozan de todas las propiedades de lasfunciones
normales,incluyendolacapacidaddesobrecarga
VeamosuncasoconcretoconunafuncingenricaqueutilizatantounaclaseVector
comounentero:
#include <iostream.h>
class Vector
{
public:
float x, y;
bool operator>(Vector v)
{
return ((x*x + y*y) > (v.x*v.x + v.y*v.y))? true: false;
}
};
template<class T> T max(T a, T b){ return (a > b) ? a : b;}
void main()
{
Vector v1 = {2, 3}, v2 = {1, 5};
int x = 2, y = 3;
cout <<"Mayor: "<<max(x, y)<< endl;
cout <<"Mayor:"<<max(v1, v2).x<<", "<<max(v1,v2).y << endl;
}
Elresultadodeejecutarelprogramaeselsiguiente:
Mayor:3
Mayor:1,5
Otro ejemplo clsico en la definicin de una plantilla de funcin es el caso de la
funcinpermutar:
#include <iostream.h>
template <class S> void permutar(S&, S&);
void main(void)
{
void main(void)
{
float mivector[10]={2,4,6,8,1,3,5,7,9,0};
char cadena[10]="efghBACDI";
ordenar(mivector,8);
ordenar(cadena,10);
for(i=0;i<10;i++)cout<<mivector[i];
cout<<endl<<cadena;
}
a = b;
b = temp;
}
template <class T> void ordenar (T *vector, int num)
{
int i,j;
for(i=0;i<num-1;i++)
for(j=i+1;j<num;j++)
if(vector[i]<vector[j])permutar(vector[i],vector[j]);
}
Metodos genricos
Lasfuncionesgenricaspuedensermiembros(mtodos)declases:
class A
{
template<class T> void func(T& t) // def de mtodo genrico
{
...
}
...
}
Aunqueannosehanexplicadolasclasesgenricas,esconvenienteindicaryaque
los miembros genricos pueden ser a su vez miembros de clases genricas, en cuyo caso
pueden hacer uso de los parmetros de la plantilla de clase genrica. Un ejemplo de un
mtodogenricoeselsiguiente:
#include <iostream.h>
class A
{
public:
int x;
template<class T> void fun(T t1, T t2);
A (int a = 0) { x = a; }
};
void main(void)
{
A a(7), b(14);
a.fun(2, 3);
b.fun('x', 'y');
}
Salida:
Valor1:2,Valor2:3,Valorx:7
Valor1:x,Valor2:y,Valorx:14
Parmetros de la plantilla
Ladefinicindelafuncingenricapuedeincluirmsdeunargumento.Esdecir,el
especificador template <...> puede contener una lista con varios tipos. Estos parmetros
puedensertiposComplejosofundamentales,porejemplounint;inclusoespecializacionesde
clasesgenricasyconstantesdetiempodecompilacin.
Engenerallosparmetrosdeunaplantillapuedenser:
Identificadoresdetipo,porejemploT.Estosparmetrosvanprecedidospor
lapalabrareservadaclassotypename:
template<classA,classB>voidfunc(A,B);
template<typenameA,typenameB>voidfunc(A,B);
186 PROGRAMACIN C++ Y COMUNICACIONES.
Plantillasdeclases(adelantandodenuevo):
template<classA,template<classt>classX>voidfunc(A,X<T>);
Parmetrosdealgnotrotipo:primitivo,derivado,definidoporelusuario,
o de plantilla. Un parmetro de plantilla que no sea un tipo, es una
constantedentrodelaplantilla,yporlotanto,nosepuedemodificar.
template<classA,intx>voidfunc(A,int);
template<classT,intp>Tfx(Tx);
Un ejemplo que ilustra este ltimo caso, es el siguiente en el que se utilizan dos
plantillasmuyparecidasdesdeelpuntodevistadeuso,perodiferentesencuantoalcdigo
compiladoeselsiguiente:
#include <iostream.h>
Losargumentosalaplantilladelasfuncionesgenricasnopuedentenervalorespor
defecto. Lo mismo que en las funciones explcitas, en las funciones genricas debe existir
concordanciaentreelnmeroytipodelosargumentosformalesyactuales.
template <class A, int x> void func(A, int);
...
imprime2(vector);
EnestecasoelcompiladornotieneposibilidaddededucireltipodelargumentoB.
Enocasioneseldiseodelafuncinnopermitedeterminareltipodeparmetrode
la plantilla a partir de los argumentos actuales de la invocacin (o sencillamente se quiere
obligaralcompiladoraaplicarlosargumentosactualesaunaespecializacininstanciadacon
unosparmetrosconcretos).Porejemplo:
template <class T> T* construir ()
{
T *aux=new T;
188 PROGRAMACIN C++ Y COMUNICACIONES.
if(aux==NULL)
{
cout<<Error de construccin;
abort();
}
return aux;
}
Laplantillaanteriorcreaunobjetodecualquiertipoydevuelveunpunteroalobjeto
creado, o aborta el programa en caso de no haber podido crearlo. Se observa que el
compilador no puede deducir el tipo de parmetro a utilizar con la plantilla a partir del
argumentoactual,puestoqueenestecasonohayargumentoactual.Lasiguientelneasera
errnea:
int* iptr = construir();
Elcompiladorarrojaraelmensaje:ERROR,parmetroTdesconocido.
Para su utilizacin debe especificarseexplcitamente el tipode parmetro a utilizar
medianteunargumentodeplantilla:
int* iptr = construir<int>();
Estaformadeinstanciarunaplantillasedenominainstanciacinimplcitaespecfica
delaplantillaoespecificacinexplcitadelosparmetrosdelaplantilla,yenestoscasosla
lista <...> que sigue al nombre de la funcin genrica puede incluir los parmetros de la
plantilla que sean necesarios. Esta lista no tiene porqu incluir a todos los parmetros
actualmente utilizados por la plantilla, ya que el compilador la completa con los tipos que
puedan deducirse de la lista de argumentos de la funcin. Sin embargo, los parmetros
faltantes deben ser los ltimos de la lista <...> (anlogo a lo exigido a los argumentos por
defectoenlasfuncionesexplcitas).Porejemplo:
template <class A, class B, class C> void func(B b, C c, int i);
....
func(b, c, i); // Error!!
func <A, B, C>(b, c, i); // Ok. B y C redundantes
func<A>(b, c, i); // Ok.
func<A>(b, c); // Error!! falta argumento i
Un aspecto crucial de las funciones genricas es que el compilador debe poder
deducir sin ambigedad los argumentos de la plantilla a partir de los argumentos utilizados
paralainvocacindelafuncin.
Recordemos que en los casos de sobrecarga, la invocacin de funciones C++ utiliza
un sistema estndar para encontrar la definicin que mejor se adapta a los argumentos
actuales.Tambinserealizantransformacionesautomticascuandolosargumentospasados
a la funcin no concuerdan exactamente con los esperados (argumentos formales) Estos
mecanismosutilizanunasreglasdenominadascongruenciaestndardeargumentos
Encasodelasplantillasdefuncinofuncionesgenricas,elcompiladordeducelos
parmetrosdelaplantillamedianteelanlisisdelosargumentos actuales de la invocacin,
peroparaestosolorealizaconversionestriviales(menossignificativasquelasrealizadascon
lasfuncionesexplcitas).Lossiguientesejemplospuedenayudarailustrarestasconversiones
tantoparaunafuncingenricacomoparaunanormaloexplcita:
template<class T> bool igual(T a, T b)
{
return (a == b) ? true : false;
}
bool desigual(double a, double b)
{
return (a == b) ? false : true;
}
...
int i;
char c;
double d;
...
igual(i, i); // Ok. invoca igual(int ,int)
igual(c, c); // Ok. invoca igual(char,char)
igual(i, c); // Error!! igual(int,char) indefinida
igual(c, i); // Error!! igual(char,int) indefinida
desigual(i, i) // Ok. conversin de argumentos efectuada
desigual(c, c) // Ok. conversin de argumentos efectuada
desigual(i, c) // Ok. conversin de argumentos efectuada
desigual(d, d) // Ok. concordancia de argumentos
190 PROGRAMACIN C++ Y COMUNICACIONES.
Hemossealadoquelainstanciacindelaplantillaserealizacuandoelcompilador
encuentraunainvocacindelafuncingenricaoseobtienesudireccinyquesolopuede
existirunaversindecadaespecializacindelafuncingenrica.Estaspremisasconducena
queseaposibleevitarlageneracinautomticaparaunoovariostiposconcretos,mediante
dosprocedimientos:
Forzarunainstanciacinespecficadelaplantilla(instanciacinexplcita),de
forma que se genera el cdigo de una especialidad concreta, con
independencia de que posteriormente se requiera o no, la utilizacin del
cdigogenerado.Lainstanciacinpuederealizarsededosformas:
o Forzar la instanciacin de la plantilla "tal cual" para un tipo
particular. Esta instancia explcita tendra el comportamiento
genrico definido en la plantilla, por lo que la denominamos
instanciacinexplcitageneral.
o Forzar una instanciacin para un tipo particular en las mismas
condiciones que el anterior (con independencia de la posible
utilizacin del cdigo generado en el programa), pero definiendo
un nuevo comportamiento, distinto del general definido en la
plantilla. En otras palabras: instanciar una versin sobrecargada
de la funcin para un tipo especfico. La denominamos
instanciacinexplcitaparticular.
Como veremos a continuacin, estas posibilidades tienen distinta utilidad y ligeras
diferencias de detalle. Aunque son tcnicas diferentes, el resultado final es anlogo: la
existencia de una (o varias) especializaciones concretas de la funcin, lo que nos obligar a
contemplarunageneralizacindelasobrecargadefuncionesqueincluyafuncionesexplcitas
ygenricas.
#include <iostream.h>
class Vector
{
public:
float x, y;
Vector(float a,float b):x(a),y(b){}
bool operator==(const Vector& v)
{
return ( x == v.x && y == v.y)? true : false;
}
};
template<class T> bool igual(T a, T b) funcin genrica
{
return (a == b) ? true : false;
}
void main()
{
192 PROGRAMACIN C++ Y COMUNICACIONES.
Lasalidadeesteprograma,comoeradeesperareslasiguiente:
vectoresdistintos
doublesdistintos
enterosdistintos
Versin explcita
Consideremos ahora que es necesario rebajar la exigencia para que dos variables
sean consideradas iguales en el caso de que sean doubles. Para ello introducimos una
instancia de igual codificada manualmente en el que reflejamos la nueva condicin de
igualdad:
#include <iostream.h>
class Vector
{
public:
float x, y;
Vector(float a,float b):x(a),y(b){}
bool operator==(const Vector& v)
{
return ( x == v.x && y == v.y)? true : false;
}
};
template<class T> bool igual(T a, T b)
{
return (a == b) ? true : false;
};
bool igual(double a, double b) // versin explcita
{
return (labs(a-b) < 1.0) ? true : false;
};
void main()
{
Vector v1(2, 3), v2 (1, 5);
int x = 2, y = 3;
double d1 = 2.0, d2 = 2.2;
vectoresdistintos
doublesiguales
enterosdistintos
Laversinexplcitaparatiposdoubleutilizalafuncindelibreralabsparaconseguir
que dos doubles sean considerados iguales si la diferencia es solo en los decimales. La
inclusin de esta definicin supone que el compilador no necesita generar una versin de
igual()cuandolosparmetrossontipodouble.Enestecaso,elcompiladorutilizalaversin
suministrada"manualmente"porelprogramador.
Adems de permitir introducir modificaciones puntuales en el comportamiento
general, las versiones explcitas pueden utilizarse tambin para eliminar algunas de las
limitacionesdelasfuncionesgenricas.
Porejemplo,sisustituimoslasentencia:
if ( igual(d1, d2) ) cout << "doubles iguales" << endl;
por:
if ( igual(d1, y) ) cout << "doubles iguales" << endl;
194 PROGRAMACIN C++ Y COMUNICACIONES.
Seobtieneunerrordecompilacin:Couldnotfindamatchfor'igual<T>(double,int)'.
Laraznesque,comohemosvisto,elcompiladornorealizaningntipodeconversinsobre
eltipodelosargumentosutilizadosenlasfuncionesgenricas,yenestecasonoexisteuna
definicin de igual() que acepte un double y un int. En cambio, la misma sustitucin de
cuando existe una versin explcita para igual(double double), no produce ningn error. La
razn es que para las funciones normales el compilador si es capaz de realizar
automticamente determinadas transformaciones de los argumentos actuales para
adecuarlosalosesperadosporlafuncin.
Observelasintaxisutilizada:lalistadeparmetros<...>sehacambiadodeposicin
respectoaladeclaracindelaplantilla.
Enlascondicionesanterioreselcompiladorpuedegenerarunerror,unaadvertencia,
o sencillamente ignorar el segundo requerimiento, ya que previamente existe una versin
explcitadelafuncinconidnticafirma.Encualquiercasoesunareglaqueelcompilador
dar preferencia a una funcin normal (versin explcita) sobre cualquier forma de
instanciacin,explcitaoimplcita,alutilizarunafuncin.
class mVector
{
int dimension;
public:
Vector* mVptr;
mVector(int n = 1)
{
dimension = n;
mVptr = new Vector[dimension];
}
~mVector() { delete [] mVptr; }
Vector& operator[](int i) { return mVptr[i]; }
void mostrar(int);
};
void mVector::mostrar (int i)
{
if((i >= 0) && (i <= dimension)) mVptr[i].mostrar();
}
Elsistemadeplantillaspermitedefinirunaclasegenricaqueinstancieversionesde
mVectorparamatricesdecualquiertipoespecificadoporunparmetro.Laventajadeeste
diseo parametrizado, es que cualquiera que sea el tipo de objetos utilizados por las
especializaciones de la plantilla, las operaciones bsicas son siempre las mismas (insercin,
borrado,seleccindeunelemento,etc).
Ladefinicindeunaclasegenricatieneelsiguienteaspecto:
template<lista-de-parametros> class nombreClase
{
...
};
Una clase genrica puede tener una declaracin adelantada (forward) para ser
declaradadespus:
Observequeladefinicindeunaplantillacomienzasiemprecontemplate<...>,yque
losparmetrosdelalista<...>nosonvalores,sinotiposdedatos.
Ladefinicindelaclasegenricacorrespondientealcasoanterioreslasiguiente:
template<class T> class mVector
{
int dimension;
public:
T* mVptr;
mVector(int n = 1)
{
dimension = n;
mVptr = new T[dimension];
}
~mVector() { delete [] mVptr; }
T& operator[](int i) { return mVptr[i]; }
void mostrar (int);
};
Observequeapartedelcambiodeladeclaracin,sehansustituidolasocurrenciasde
Vector(untipoconcreto)porelparmetroT.Observetambinladefinicindemostrar()que
serealizaofflineconlasintaxisdeunafuncingenrica.
Recordemosqueenestasexpresiones,elespecificadorclasspuedesersustituidopor
typename,deformaquelaprimeralneapuedesersustituidapor:
{
...
};
Veamoselejemplocompleto:
#include <iostream.h>
class Vector
{
public:
int x, y;
Vector& operator= (const Vector& v)
{
x = v.x; y = v.y;
return *this;
}
void mostrar(){cout << "X = " << x << "; Y = " << y << endl;}
};
void main()
{
mVector<Vector> mV1(5);
mV1[0].x = 0; mV1[0].y = 1;
mV1[1].x = 2; mV1[1].y = 3;
mV1[2].x = 4; mV1[2].y = 5;
mV1[3].x = 6; mV1[3].y = 7;
mV1[4].x = 8; mV1[4].y = 9;
mV1.mostrar();
mVector<Vector> mV2 = mV1;
mV2.mostrar();
mV1[0].x = 9; mV1[0].y = 0;
mV2.mostrar(0);
mV1.mostrar(0);
mVector<Vector> mV3(0);
mV3.mostrar();
mV3 = mV1;
mV3.mostrar();
}
Salida:
Matriz de: 5 elementos.
0 - X = 0; Y = 1
1 - X = 2; Y = 3
2- X = 4; Y = 5
3- X = 6; Y = 7
200 PROGRAMACIN C++ Y COMUNICACIONES.
4- X = 8; Y = 9
Matriz de: 5 elementos.
0- X = 0; Y = 1
1- X = 2; Y = 3
2- X = 4; Y = 5
3- X = 6; Y = 7
4- X = 8; Y = 9
X = 0; Y = 1
X = 9; Y = 0
Matriz de: 0 elementos.
Matriz de: 5 elementos.
0- X = 9; Y = 0
1- X = 2; Y = 3
2- X = 4; Y = 5
3- X = 6; Y = 7
4- X = 8; Y = 9
Otroejemploquedescribeunaclasegenricaparalarealizacindeunapiladedatos
sin que se utilicen listas enlazadas y reserva dinmica de memoria adicional durant
funcionmientodeunobjetodeunaclaseinstanciadaeselsiguiente:
// fichero Pila.h
template <class T>
// declaracin de la clase
class Pila
{
public:
Pila(int nelem=10); // constructor
void Poner(T);
void Imprimir();
private:
int nelementos;
T* cadena;
int limite;
};
// definicin del constructor
template <class T> Pila<T>::Pila(int nelem)
{
nelementos = nelem;
cadena = new T(nelementos);
limite = 0;
};
// definicin de las funciones miembro
template <class T> void Pila<T>::Poner(T elem)
{
if (limite < nelementos)
cadena[limite++] = elem;
};
template <class T> void Pila<T>::Imprimir()
{
int i;
for (i=0; i<limite; i++)
cout << cadena[i] << endl;
};
Elprogramaprincipalpuedeserelquesigue:
#include <iostream.h>
#include "Pila.h"
void main()
{
Pila <int> p1(6);
p1.Poner(2);
p1.Poner(4);
};
Estasconsideracioneshacenquelosprototipospuedanserdejadoscomosigue(los
datosfaltantespuedenserdeducidosporelcontexto):
template<class T> class mVector
{
int dimension;
public:
T* mVptr;
mVector& operator= (const mVector&);
mVector(int); // constructor por defecto
~mVector(); // destructor
mVector(const mVector& mv); // constructor-copia
T& operator[](int i) { return mVptr[i]; }
void mostrar (int); // funcin auxiliar
void mostrar (); // funcin auxiliar
};
Sinembargo,lasdefinicionesdemtodosrealizadasoffline(fueradelcuerpodeuna
plantilla)debenserdeclaradasexplcitamentecomofuncionesgenricas.
Porejemplo:
template <class T> void mVector <T>::mostrar (int i)
{
...
}
Miembros estticos
Las clases genricas pueden tener miembros estticos (propiedades y mtodos).
Posteriormente cada especializacin dispondr de su propio conjunto de estos miembros.
Estos miembros estticos deben ser definidos fuera del cuerpo de la plantilla, exactamente
igualquesifuesenmiembrosestticosdeclasesconcretas:
template<class T> class mVector
{
...
static T* mVptr;
static void mostrarNumero (int);
...
};
Mtodos genricos
Hemossealadoque,porsupropianaturaleza,losmtodosdeclasesgenricassona
su vez (implcitamente) funciones genricas con los mismos parmetros que la clase, pero
puedenserademsfuncionesgenricasexplcitas(quedependandeparmetrosdistintosde
laplantillaaquepertenecen):
template<class X> class A
{
Segnesusual,ladefinicindelmiembrogenricopuedeefectuarsededosformas,
inlineuoffline:
#include <iostream.h>
{
x = i;
xptr = b;
}
};
int main(void)
{
char c = 'c'; char* cptr = &c;
int x = 13; int* iptr = &x;
A<int> a(iptr, 2);
A<char> b(cptr, 3);
a.fun(2, 3);
a.fun('x', 'y');
b.fun(2, 3);
b.fun('x', 'y');
return 0;
}
Salida:
Porejemplo:
mVector<char> mv1;
mVector mv2 = mv1; // Error !!
mVector<char> mv2 = mv1; // Ok.
Sin embargo, como veremos a continuacin, las clases genricas pueden tener
argumentospordefecto,porloqueenestoscasosladeclaracinpuedenoserexplcitasino
implcita(referidaalosvalorespordefectodelosargumentos).Laconsecuenciaesqueen
estoscasoselcompiladortampocorealizaningunasuposicinsobrelosargumentosautilizar.
Las clases genricas pueden ser utilizadas en los mecanismos de herencia. En ese
caso,laclasederivadaestarparametrizadaporlosmimmosargumentosquelaplantilladela
clsebase.
Porejemplo:
template <class T> class Base { ... };
template <class T> class Deriv : public Base<T> {...};
Los typedef son muy adecuados para acortar la notacin de objetos de clases
genricascuandosetratadedeclaracionesmuylargasonointeresanlosdetalles.
Porejemplo:
typedef basic_string <char> string;
string st1;
Las clases genricas pueden tener argumentos por defecto, en cuyo caso, el tipo T
puedeomitirse,peronolosngulos<>.Porejemplo:
template<class T = int> class mVector {/* ... */};
...
mVector<char> mv1; // Ok. argumento char explcito
mVector<> mv2; // Ok. argumento int implcito
Cada instancia de una clase genrica es realmente una clase, y sigue las reglas
generales de las clases. Dispondr por tanto de su propia versin de todos los miembros
estticos si los hubiere. Estas clases son denominadas implcitas, para distinguirlas de las
definidas"manualmente",quesedenominanexplcitas.
La primera vez que el compilador encuentra una sentencia del tipo
mVector<Vector> crea la funcinclase para dicho tipo; es el punto de instanciacin. Con
206 PROGRAMACIN C++ Y COMUNICACIONES.
objetodequesoloexistaunadefinicindelaclase,siexistenmsocurrenciasdeestemismo
tipo,lasfuncionesclaseredundantessoneliminadasporelenlazador.Porlarazninversa,si
el compilador no encuentra ninguna razn para instanciar una clase (generar la funcin
clase), esta generacin no se producir y no existir en el cdigo ninguna instancia de la
plantilla.
Al igual que ocurre con las funciones genricas, en las clases genricas tambin
puedeevitarselageneracindeversionesimplcitasparatiposconcretosproporcionandouna
especializacinexplcita.
Porejemplo:
class mVector<T> { ... }; // definicin genrica
...
class mVector<char> { ... }; // definicin especfica
mstarde,lasdeclaracionesdeltipo
mVector<char> mv1, mv2;
generar objetos utilizando la definicin especfica. En este caso mv1y mv2 sern
matricesalfanumricas(cadenasdecaracteres).
Observequeladefinicinexplcitacomportadosrequisitos:
Sehasustituidoeltipogenrico<T>poruntipoconcreto<char>.
Resultaevidentequeunadefinicinespecfica,comolaincluda,solotienesentidosi
senecesitanalgunasmodificacioneseneldiseocuandolaclaseserefieraatiposchar.
Argumentos de la plantilla
La declaracin de clases genricas puede incluir una lista con varios parmetros.
Estos pueden ser casi de cualquier tipo: Complejos, fundamentales, por ejemplo un int, o
inclusootraclasegenrica(plantilla).Ademsentodosloscasospuedenpresentarvalores
pordefecto.:
template<class T, int dimension = 128> class mVector { ... };
Aligualqueenlasfuncionesgenricas,enlainstanciacindeclasesgenricas,los
valoresdelosparmetrosquenoseantiposComplejosdebenserconstantesoexpresiones
constantes.
const int K = 128;
int i = 256;
mVector<int, 2*K> mV1; // OK
mVector<Vector, i> mV2; // Error: i no es constante
Este tipo de parmetros constantes son adecuados para establecer tamaos y
lmites.Sinembargo,porsupropianaturalezadeconstantes,cualquierintentoposteriorde
alterarsuvalorgeneraunerror.
Los argumentos tambin pueden ser otras plantillas, pero solo de clases genricas.
Introducircomoargumentounaplantilladefuncionegenricanoestpermitido:
template <class T, template<class X> class C> class MatrizC
{ ...
};
template <class T, template<class X> void Func(X a)> class MatrizF
{ // Error!!
...
};
Merecenespecialatencinlassentenciasdondeseutilizanpunterosamiembrosde
clases implcitas. El tipo de clase est definido en los parmetros. Observe que fptr1 es
punteroamtododeclaseMatriz<char,5>,ynopuedereferenciarunmtododem3,quees
unobjetodetipoMatriz<char,1>.
p1.Imprimir();
Pila <char> p2(6);
p2.Poner('a');
p2.Poner('b');
p2.Imprimir();
}
AlprincipiodelcapitulosehasealadoquelasplantillasfueronintroducidasenC++
paradarsoporteadeterminadastcnicasutilizadasenlaLibreraEstndar;dehecho,laSTL
est constituida casi exclusivamente por plantillas. Hablar y utilizar en profundidad las
plantillas de la librera estndar puede permitirnos el reducir drsticamente el esfuerzo
Una idea bsica dentro de las STL es el contenedor, que es precisamente lo que
parece: un sitio en el que almacenar cosas. Ya se ha visto que una de las operaciones ms
habituales es esta, as como una de las justificaciones para el uso de plantillas de clases
(recurdese el ejemplo de Lista<Esferas> o de la clase genrica mVector. Habitualmente
necesitamos este tipo de sitios de almacenamiento cuando de antemano desconocemos
cuantosobjetosodatosvamosatener.LoscontenedoresdelaSTLhacenesto;soncapaces
de mantener colecciones de objetos y adems se pueden redimensionar. El modo como
almacenanestascoleccionesdeobjetos,ycomoconsecuencialasoperacionesquesepueden
realizar sobre las colecciones, hacen que aparezcan distintos tipos de contenedores. Los
contenedoresmssecillosson:
vector. Un vector es la versin STL de una matriz dinmica de una dimensin. Las
instanciasdeestaclasegenricaconformanunasecuencia(unaclasedecontenedor).La
clasedisponedeaccesoaleatorioasuselementosydeunmecanismomuyeficientede
insercinyborradodeelementosalfinal.Aunquetambinpuedeninsertarseyborrarse
elementosenmedio,porelmodoenqueseorganizanloselementosenmemoria,esta
operacin es muy poco eficiente. Est definida en el fichero <vector> y responde a la
siguientedeclaracin:
template <class T, class Allocator = allocator<T> > class vector;
deque. Esmuyparecidoavector,unasecuencialinealdeelementos,peroadmitecon
eficiencia la insercin de objetos tanto al principio como al final, mientras que sigue
comportndosemalparainsercionesintermedias.Admiteelaccesoaleatoriocasiconla
mismaeficienciaquevector,peroesespecialmentemsrpidocuandorequieresolicitar
msespacioparaalmacenarmsdatos(redimensionamiento).
list.Lasinstanciasdeestaplantillaconformantambinunasecuenciaquedisponede
mecanismosmuyeficientesparainsertaryeliminarelementosencualquierpunto.Est
internamente implementada como una lista doblemente enlazada. Como consecuencia
210 PROGRAMACIN C++ Y COMUNICACIONES.
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() {};
};
int main() {
Container shapes;
shapes.push_back(new Circle);
shapes.push_back(new Triangle);
for(Iter i = shapes.begin();
i != shapes.end(); i++)
(*i)->draw(); //se puede usar i->draw() dado que el iterador tiene
//sobrecargado el operador ->
// ... al final si queremos limpiar la memoria:
for(Iter j = shapes.begin();
j != shapes.end(); j++)
delete *j;
}
Esinteresanteverqueesposiblecambiarsinproblemaseltipobsicodelcontenedora
una lista o un deque, y el cdigo no se ve alterado ms que en la definicin del
contenedor.
Algunasotrasclaseshabitualmenteutilizadas,seranlassiguientes:
basic_string: una plantilla para utilizar entidades como secuencias de caracteres. Est
definidaenelficherodecabecera<string>,yrespondealasiguientedeclaracin:
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> > class basic_string;
Comopuedeverse,aceptatresargumentos,delosquedostienenvalorespordefecto.
Existendosespecializacionesquetienennombresespecficos.EnconcretosicharTes
charlaespecializacinsedenominastring,ywstringsicharTeswchar_t.Estosehace
mediantesendostypedef:
typedef basic_string <char> string;
212 PROGRAMACIN C++ Y COMUNICACIONES.
int main() {
string s1("This ");
string s2="That ";
string s3("The other ");
// operator+ concatena strings
s1 = s1 + s2;
cout << s1 << endl;
// otra forma de concatenar strings
s1 += s3;
cout << s1 << endl;
// o acceder a la vez que se concatena a un caracter
s1 += s3 + s3[4] + "oh lala";
cout << s1 << endl;
if(s1 != s2) {
cout << "los strings son distitos:" << " ";
if(s1 > s2)
cout << "s1 es > s2" << endl;
else
cout << "s2 es > s1" << endl;
}
}
map.Estaplantillaestdefinidaenelfichero<map>,ytienelasiguientedeclaracin:
template <class Key, class T, class Compare = less<Key>
class Allocator = allocator<pair<const Key, T>> > class map;
auto_ptr.Estaplantillagenerapunteros"inteligentes"quedestruyenautomticamente
elobjetosealadocuandoellosmismossalendembito.Sudefinicinestenelfichero
<memory>,ysudeclaracines:
template <class X> class auto_ptr;
EnrealidadestaplantillasehaincluidoenlaLibreraEstndarparaayudararesolver
el problema de los objetos persistentes, creados con el operador new, cuyo
referente (el puntero que los seala) es un objeto automtico que puede ser
destruido inadvertidamente al salir de mbito. Lo que puede ocurrir en el los
procesosdelanzamientoycapturadeexcepciones.
6.6. Ejemplo
Elsiguienteestractodecdigomuestraunaclasegenricaquesirveparaalamecenar
punteros de objetos o elementos creados externamente a ella. Internamente se comporta
comounvectordinmicoqueadmiteportantounnmeroindefinidodeelementos.Incluye
adems una serie de operaciones bsicas para facilitar el manejo y mantenimiento del
conjuntodedireccionesalmacenadas:
Ficherocontenedor.h
template <class T> class contenedor
{
private:
T **array;
int nElem;
int elemMax;
public:
contenedor(void);
contenedor(contenedor &td); /*copia*/
~contenedor(void);
inline T* operator [] (int a);
void operator += (T *ele);
void destruirObjetos(void);
void eliminar (int a);
214 PROGRAMACIN C++ Y COMUNICACIONES.
T* quitar(int a);
T* quitar(T* ele);
int buscar(T* ele);
void swap(int a, int b);
void insertar(T *ele, int a);
inline int numElem (void);
};
Ficherocontenedor.cpp
#include contenedor.h
template <class T> contenedor<T>::contenedor (void)
{
array = new T* [5];
nElem = 0;
elemMax = 5;
}
template <class T> void contenedor<T>::destruirObjetos (void)
{
for (int i=0; i<numElem; i++)
delete array[i];
numElem=0;
}
template <class T> contenedor<T>::~contenedor (void)
{
delete [] array;
}
if (nElem == elemMax)
{
elemMax+=5;
Unodelosaspectosqueconmsdificultadseabordanenlosdistintoslenguajesde
programacineselcorrectotratamientodeloserrores.Esdecir,elfuncionamientonormalde
un algoritmo o programa contiene la dificultad inherente del problema que se quiere
resolver, y como consecuencia generar un flujograma ms o menos complicado. Sin
embargo,todoelloseincrementaencomplejidaddeformanotableenelmomentoenelque
sepretendeverificarycomprobarlosposibleserroresosituaciones"nonominales"durante
elprocesodeejecucin.
Esteproblemanoessoloespecficodelaingenieradelsoftware,sinoqueamenudo
eselmayorquebraderodecabezaenlamayoradelosproyectosdediseoyenparticular
aquellosenlosquelaseguridadesimportante.Dehecho,sepuededecirsinproblema,que
es ms Complejo el sistema de redundancia y seguridad que se incluye en el software de
controldeunavinqueelpropiosistemadecontrol.
consecuencia"manejadordeexcepciones6".Existenmuchostiposdeexcepciones,peropara
ubicar el tema, durante la ejecucin de un programa puede ocurrir que un fichero no se
pueda grabar (disco lleno), o que se agote la memoria, o que el usuario haya intentado
realizarunaoperacinnovlida(porejemplodesdeelprogramaabrirunficherosobreelque
carecedepermiso),etc.
1. Hayunapartedecdigoenelqueseconsideraquesepuedenproducirsituaciones
anmalas,yqueconsecuenciasepuedengenerarunaseriedeexcepciones.Poreso,
seconsideraqueesposiblequelaaccinqueesapartedecdigoquiererealizarno
seconsiga,yportantoesunazonade"intentodeejecucin"(try).
2. Cuandosedetectaunacircunstanciaextraaoanmala(unaexcepcin),seinforma
alproceso,funcin,oprogramaquehaocurridoalgoimprevisto,yseinterrumpeel
curso normal de ejecucin. Para realizarlo se "lanza" una excepcin (throw). Esa
excepcin es un objeto que contiene informacin sobre el error para que el que
escucheseacapazdereaccionaranteestasituacin.
3. Paraqueelprogramapuedadecidirquehacerenestoscasos,trasintentarejecutar
algo susceptible de fallar, indicar una zona del cdigo que se ejecutar para
reaccionar ante esas sistuaciones. Para ello "captura" (catch) las excepciones
lanzadas en la zona de "intento" y se decide que hacer al respecto con la
informacinqueestascontienen.
En el fondo el mecanismo es un mecanismo de salto controlado. Al cdigo encargado de
reaccionaranteunadeterminadaexcepcinselodenomina"manejador"delaexcepcin.
6
Exception Handler
222 PROGRAMACIN C++ Y COMUNICACIONES.
GeneralmentelasimplementacionesC++soloconsideranlasexcepcionessncronas,deforma
quenosepuedencapturarconellasexcepcionestalescomolapulsacindeunatecla.Dicho
con otras palabras: solo pueden manejar las excepciones lanzadas con la sentencia
throw. Siguen un modelo denominado de excepciones sncronas con terminacin, lo que
significaqueunavezquesehalanzadounaexcepcin,elcontrolnopuedevolveralpunto
quelalanz.El"handler"nopuededevolverelcontrolalpuntodeorigendelerrormediante
una sentencia return. En este contexto, un return en el bloque catch supone salir de la
funcinquecontienedichobloque.
Antes de ver un ejemplo completo se ver en primer lugar como se ha previsto en C++ la
transcripcin de cada uno de estos compoenentes del mecanismo de tratamiento de
excepciones.
El bloque "try"
En sntesis podemos decir que el programa se prepara para cierta accin, decimos
que"lointenta".Paraelloseespecificaunbloquedecdigocuyaejecucinsevaaintentar
("tryblock")utilizandolapalabraclavetry:
try
{
Laideadelbloquetryenestecasopodraejemplarizarsedelasiguienteforma:
INTENTA{
1.Abrirelfichero
2.Guardarlainformacin
3.Cerrarelfichero
}
SIHAYUNERRORCAPTURALOYEJECUTA
{
4.Informaalusuario
}
Aspues,tryesunasentenciaqueenciertaformaescapazdeespecificarelflujodeejecucin
delprograma.Unbloqueintentodebeserseguidoinmediatamenteporelbloquemanejador
delaexcepcin,elcualseespecificapormediodelapalabraclavecatch.
El bloque "catch"
Mediante la palabra clave catch especificamos el cdigo encargado de reaccionar ante una
determinadaexcepcinoconjuntodeexcepciones.Comoyasehacomentado,sedicequeun
manejador"handler"capturaunaexcepcin.
EnC++esobligatorioquetrasunbloquetryseincluyaalmenosunbloquecatch,porloquela
sintaxisanteriorquedaracompletadelasiguienteforma:
}
... // continua la ejecucin normal
Lasexcepcinesnoslolaslanzanlasfuncionesincluidasdentrodelaslibrerasexternas,sino
quenosotrospodemosquererinformarquealgonohaidobiendentrodelalgicadenuestro
programa.
Al igual que ocurre con el cdigo de las libreras estandar, esto se realiza por medio de la
instruccinthrow.
EllenguajeC++especificaquetodaslasexcepcionesdebenserlanzadasdesdeelinteriorde
un bloqueintento y permite que sean de cualquier tipo. Como se ha apuntado antes,
generalmentesonunobjeto(instanciadeunaclase)quecontieneinformacin.Esteobjeto
escreadoylanzadoenelpuntodelasentenciathrowycapturadodondeestlasentencia
catch.Eltipodeinformacincontenidoenelobjetoesjustamenteelquenosgustaratener
para saber que tipo de error se ha producido. En este sentido puede pensarse en las
excepcionescomoenunaespeciedecorreosquetransportaninformacindesdeelpuntodel
error hasta el sitio donde esta informacin puede ser analizada. Todo esto lo veremos con
msdetalleacontinuacin.
Como se ha comentado C++ permite lanzar excepciones de cualquier tipo. Sin embargo lo
normalesqueseaninstanciasdeunaclasetipoX,quecontienelainformacinnecesariapara
conocer la naturaleza de la circunstancia excepcional (probablemente un error). El tipo X
debecorresponderconeltipodeargumentousadoenelbloquecatch,detalformaquepor
medio del tipo de las excepciones ser posible ejecutar manejadores distintos an siendo
estaslanzadasdesdeelmismobloquetry.
Nota:Serecomiendaquelasclasesdiseadasparainstanciarestetipode
objetos(denominadasExcepciones)seanespecficasydiseadasparaestefin
exclusivo,sinquetenganotrousoquelaidentificacinymanejodelas
excepciones.
Laexpresinthrow(Xarg)inicializarunobjetotemporalargdetipoX,aunquepuedequese
generenotrascopiaspornecesidaddelcompilador.Enconsecuenciapuedesertildefinirun
constructorcopiacuandoelobjetoalanzarperteneceaunaclasequecontienesubobjetos,
comoenelcasodecualquierotraclasecuyosobjetosquieranserpasadosporvalor
(recurdeseelapartadodedicadoalcontructordecopiayeloperadordeasignacinenel
captulo3).
EnelsiguienteejemplosepasaelobjetodetipoOutalmanejadorcatch:
#include <stdio.h>
bool pass;
class Out{}; // L.3: Para instanciar el objeto a lanzar
Comopuedeverse,lafilosofaC++respectoalmanejodeexcepcionesnoconsisteencorregir
el error y volver al punto de partida. Por el contrario, cuando se genera una excepcin el
control sale del bloque try que lanz la excepcin (incluso de la funcin), y pasa al bloque
catchcuyomanejadorcorrespondeconlaexcepcinlanzada(siesqueexiste).
Asuvezelbloquecatchpuedehacervariascosas:
Relanzarlamismaexcepcin
226 PROGRAMACIN C++ Y COMUNICACIONES.
Saltaraunaetiqueta
Terminarsuejecucinnormalmente(alcanzarlallavedecierre).
Si el bloque catch termina normalmente sin lanzar una nueva excepcin, el control se salta
todos los bloques catch que hubiese asociados al bloque try correspondiente y sigue la
ejecucindelprogramaacontinuacin.
Puede ocurrir que el bloque catch lance a su vez una excepcin. Lo que nos conduce a
excepcionesanidadas.Estopuedeocurrir,porelhechodequeseejecutanintruccionesypor
tantoesposiblequealgunadeellasvuelvaagenerarasuvezunaexcepcin(supongaseque
es una excepcin lanzada por intentar cerrar un fichero que no existe o que no se puede
cerrar)
Como se puede ver, un programador avanzado puede utilizar las excepciones C++ como un
mecanismo de return o break multinivel, controlado no por una circunstancia excepcional,
sinocomounactodeliberadodelprogramadorparacontrolarelflujodeejecucin.selanzan
deliberadamenteexcepcionesconlaideademoverseentrebloquesadistintosniveles.Dado
el nivel de este curso no se recomienda esta prctica hasta que no se est totalmente
familiarizadoconlaprogramacinestructurada.
Elsiguienteejemploseraincorrecto,dadoqueseintentarelanzarunaexcepcindesdefuera
deunbloquetry:
try {
...
if (x) throw A(); // lanzar excepcin
}
catch (A a) { // capturar excepcin
... // hacer algo respecto al error
throw; // Error!! no est en un bloque try
}
Elmodomshabitualderealizarunrelanzamientoesdebidoaquesetratadeunbloquetry
anidadoenotrobloquetry(enlamismafuncinoenfuncionesjerarquicamenteporencima
enlapiladellamadas).Elsiguienteejemploreflejaestemododeproceder:
void foo();
void main () {
try {
...
foo();
}
catch (A a) {
...
}
return 0;
}
void foo() {
...
if (x) try {
throw A();
}
catch (A) {
...
throw;
}
}
ElobjetivodeUMLesproporcionaradesarrolladoresdesoftware,arquitectosdesistemase
ingenierosdesoftwaredeherramientasparaelanlisis,diseoeimplementacindesistemas
basadosensoftware,ascomomodelarprocesosdenegocioysimilares.
CollageobtenidodeWikipediaenelquesereflejanalgunosdelosmltiplesdiagramasqueesfecificaUML.
UML cuenta con varios tipos de diagramas, los cuales muestran diferentes aspectos de las
entidadesrepresentadas.
FinalmentenohayqueconfundirUMLconunlenguajedeprogramacin.Dehecho,apesar
deconstituirunestndarprcticamenteaceptadoporelconjuntodeprogramadores,nodeja
derecibirciertascrticasdebidoalaambigedadenlainterpretacinquesepuederealizaren
los distintos diagramas. Adems, al constituir una serie de herramientas de modelado, en
general, una misma realidad se representa o dibuja desde distitnas perspectivas que se
complementan para finalmente dotar al conjunto de un significado. Luego por eso es muy
importantequelosdiagramassecentrenenaquelaspectoquequierenmostrarynointentar
reflejartodalarealidadenunsologrfico.
232 PROGRAMACIN C++ Y COMUNICACIONES.
LosdiagramasdeUMLcontienencincotiposdeelementosdiferenciados:
1. Elementosestructurales:Puedeentendersecomolarepresentacindelosnombres
dentro de un modelo de algo. Por ejemplo, en una urbanizacin, casa, rbol,
carretera. Son sustantivos del modelo. Constituyen la parte ms esttica del
modeladorepresentandotantoelementosconceptualescomofsicos.
2. Elementosdecomportamiento:deformaanloga,podemosestablecerquevienena
sercomolosverbosdellenguajedemodelado.Representancomportamientosenel
tiempo y en el espacio. Existirn elementos de comportamiento que nos servirn
paraespecificarcomoevolucionanlascosasademsdecmoserelacionan.
3. Elementos de agrupacin. Son las partes organizativas del modelo. Establece las
divisionesenquesepuedefraccionarunmodelo.
4. Elementosdeanotacin.Comosupropionombreindicasonlaspartesexplicativas
del modelo UML. Iluminan, explican, detallan aspectos de cualquier elemento del
modelo.
5. Relaciones. Nos permiten reflejar los modos en que los elementos del modelo se
relacionanentres.
Elementos estructurales
CLASE:Reflejaunconjuntodeobjetosquecompartenlosmismosatributos,operaciones,
relaciones y semntica. Lgicamente constituir una representacin unvoca del
elemento homnimo de C++. Se refleja como un rectngulo dividido en tres secciones:
nombre,atributosymtodos.
Unainterfazsuministradaporunaclasealrestodecomponentes(conjuntode
operacionesagrupadasquedanunservicio,porloqueunaclasepuedetenervarias
interfaces),seespecificapormediodeuncirculounidoporunalneaalaclase.Deigual
forma,siunaclaserequieredeaccederaunainterfazdeotrocomponente,estose
reflejapormediodeunsemicrculounidoporunsegmentoalaclase.Porejemplo,la
claseventanaimplementalaintefazIVentana,yrequieredelusodelainterfazIPaint(que
esunservicioquelepermitirdibujarseenalgnlugar):
234 PROGRAMACIN C++ Y COMUNICACIONES.
Componente: Es una parte modular del sistema de diseo, agrupando por tanto sus
elementos lgicos (clases, interfaces), y mostrando fundamentalmente un conjunto de
funcionalidades utilizables por el exterior. Por ejemplo, un componente podra ser el
reporductor de Video de un sistema de ventanas. Internamente contendr una
complejidadelevada,perofinalizadoelcomponente,loquesenecesitaparasuusoeslas
interfaces publicas del componente (abrir un fichero, reproducirlo, subir el volumen
etc).Unaspectoimportanteesqueuncomponenteenprincipiopuedeserintercambiado
porotrosiemprequesemantengalainterfaz.
Nodo: Elemento fsico que existe en tiempo de ejecucin y que representa un recurso
computacional que, por lo general, dispone de algo de memoria y, con frecuencia, de
capacidaddeprocesamiento.Unconjuntodecomponentespuederesidirenunnodo.
Elementos de comportamiento
Interaccin:Comportamientoquecomprendeunconjuntodemensajesintercambiadosentre
un conjunto de objetos, dentro de un contexto particular para conseguir un propsito
especfico. Involucra otros muchos elementos, incluyendo mensajes, secuencias de accin
(comportamientoinvocadoporunobjeto)yenlaces(conexionesentreobjetos)
Estado:Seutilizaparareflejarenunasecuencialosestadosporlosquepasaunobjetoouna
interaccinenrespuestaaeventozosucesosengeneral.
Elementos de agrupacin
Paquete:Esunmecanismodepropsitogeneralparaorganizarelementos(estructurales,de
comportamiento, e incluso otros elementos de agrupacin ) en grupos. Al contrario de los
componentes (que existen en tiempo de ejecucin), un paquete es puramente conceptual
(sloexisteentiempodedesarrollo).Unpaqueteformaunespaciodenombres,ysepideen
anidar,aunquedebenavistarsepasquetesmuyanidados:
Elementos de anotacin
Nota: el tipo principal de anotacin. Son comentarios que se pueden aplicar para describir,
clarificaryhacerobservacionescobrecualquierelementodeunmodelo
Elementos de relacin
Una relacin es una conexin entre elementos. Para diferenciar las distintas relaciones se
utilizan diferentes tipos de lneas. Hay cuatro tipos de relaciones: dependencia, asociacin,
generalizacinyrealizacin
236 PROGRAMACIN C++ Y COMUNICACIONES.
Asociacin:Relacinestructuralquedescribeunconjuntodeenlaces,loscualssonrelaciones
entre objetos. La agregacin es un tipo especila de asociacin y representa una relacin
estructuralentreuntodoysuspartes.
ElmodeladoeslapartedeUMLqueseocupadeidentificartodaslaspartesimportantesde
un sistema as como sus interacciones. De igual forma se entiende como modelado
estructural, al modelo de los aspectos estticos de un sistema, para lo cual se utilizan
fundamentalmente como sustantivos o elementos estructrales bsicos las clases y las
interfaces as como sus relaciones entre ellas. Dado que en estos apuntes slo se pretende
darunasnocionesquenospermitanrepresentarlaestructuradeclasesyalgodelaevolucin
denuestrosprogramas,seprocedeahroaaverloselementosmscomunesenestetipode
diagramasdenominadosDCD(DiagramasdeClasesdeDiseo).
La forma en que representamos las interacciones entre clases queda reflejado por sus
relaciones. En los diagramas de modelado sin embargo no hay porque reflejar TODAS las
relacionesexistentes,porqueenesecasoeldiagramapuedeconvertirseenalgoilegible.Las
relacionesmshabituales(yesaquendondenoscentraremosenestecurso,dejandootros
diagramasyrelacionesparamsadelante)son:
Relacindedependencia:
Uncambioenlaespecificacindelelementoindependientepuedeafectaralotroelemento
implicado en la relacin. En el ejemplo tanto la Televisin como el Grabador USAN un
determinadoCanal.Deformaquesicambialainterfazoelcomportamientodelosobjetosde
tipo Canal, habra que modificar el Grabador y la Televisin, cosaque no ocurre ensentido
contrario.Luegoexisteunadependenciaentreclases.EsimportantedestacarqueelCanalno
necesitaconoceralGrabadornialaTelevisin.EnC++estarelacinhabitualmentesetraduce
enunasentencia#includequepermiteusarlaclasedelacualsedepende.
RelacindeGeneralizacin:
Eslarelacinqueseestableceentreunconceptooelementogeneral(superclase)yuncaso
msespecficodeeseelemento(subclaseohijo).Elcasomsclaroeseldeunaclase(hija)
que hereda de otra clase (padre). Como se coment anteriormente, los objetos hijos se
podrnutilizarencualquierlugardondeaparezcaunobjetodetipopadre.
238 PROGRAMACIN C++ Y COMUNICACIONES.
RelacindeAsociacin:
Mediante esta relacin representamos como los objetos de un elemento estn conectados
conlosobjetosdeotros.Puedenestablecerseinclusorelacionesrecursivas,esdecirqueun
objetoestasociadoaunobjetodelmismotipo.
Enlasrelacionesdeasociacinsesuelenincluiradornosparafacilitarsucomprensin,ypara
diferenciarlosdistintosmodosquelaasociacinpuederealizarse:
Agregacin:Representaunarelacinestructuralentreiguales(sirvepararelacionar
todo/parte,peroenelquetantoeltodocomolapartetienenunavidapropia.En
C++reflejaagregacionesdeobjetosporreferencia.
Composicin:Comounaagregacinsimpleperoenestecasoeltododalavidaala
parte.EnC++,reflejaelhechodequeunobjetooconjuntodeobjetossonatributos
delobjetoqueloscontiene.
240 PROGRAMACIN C++ Y COMUNICACIONES.
8.3. Diagramas
DiagramasdeClases:
Dado que solo se trata de una breve introduccin, incluimos en este captulo uno de los
diagramasmsrecurrentementeutilizadosenDOO,eldiagramadeclasesdediseo.Eneste
semuestraunconjuntodeclases,coninterfaces,colaboracionesysusrelaciones.
Se usa fundamentalmente para modelar el vocabulario del sistema (abstracciones que son
partedelsistemaylasquenoloson)ascomomodelarcolaboracionessimples,yelesquema
lgicodeunabasededatos.Portantoseutilizanparavisualizarlosaspectosestticosdelos
bloquesdeconstruccindelsistema.
Paratrazarundiagramadeclasesenelquesereflejenlascolaboracionessimples,enprimer
lugar habr que identificar las funciones o comportamientos del sistema que se est
modelando,yquequedarnreflejadosporeldiagrama.
Paracadaelementoentonces,habrqueidentificarlasclases,iterfacesyrelacionesconotros
elementos.Habrqueirdontandoaestoselementosdecontenido,intentandoquehayaun
repartoderesponsabilidadesentreclasesyterminandoporconvertirlasresponsabilidaders
enatributos.
DiagramasdeSequecia:
Otrodelosdiagramasmsrecurrentescuandosedeseareflejarelcomportamientodinmico
delasinteraccionesentredistintoselementoseseldiagramadesecuencia.
Semodelanlosaspectosdinmicosdeunsistemamedianteinteracciones.Unainteraccines
un comportamiento que comprende un conjunto de mensajes intercambiados entre un
conjuntodeobjetosdentrodeuncontextoparalograrunpropsitoyseutilizaparamodelar
elflujodecontroldentrodeunaoperacin,unaclase,uncomponente,uncasodeusooel
propio sistema. En este contexto, se considera un mensaje a la especificacin de una
comunicacin entre objetos que transmite informacin, con la expectativa de que se
desencadenarunaactividad.Lostiposbasicosdemensajeson:
Llamada:Invocaunaoperacinsobreunobjeto
Retorno:Devuelveunvaloralinvocador
Envo:Envaunasealaunobjeto
Creacin
Destruccin
Los objetos que participan en una interaccin son o bien elementos concretos (objetos) o
bienelementosprototpicos(clases,nodos,actoresycasosdeuso).
Undiagramadesecuenciaseraelreflejadoacontinuacin:
242 PROGRAMACIN C++ Y COMUNICACIONES.
Algunascaractersticasdestacabesson:
Lalneadevidadelasinstanciasoclases:Representalaexistenciadeunobjetoalolargode
unperiododetiempo.Sisecreanodestruyenobjetosdurantelainteraccin,suslneasde
vida aparecen y desaparecen cuando reciben los mensajes estereotipados >>create>> y
<<destroy>>respectivamente.Lalneadevidasonlaslneasverticalesdeldiagrama.
Elfocodecontrol:elcualrepresentaelperiododetiempoduranteelcualunobjetoejecuta
unaaccin.Serepresentanconrectngulosvacossobrelalneadevida.
Asuvezlosmensajessepuedenclasificaradicionalmentecomo:
Tambinserepresentalarespuestaaunmensajeconunaflechadiscontinua
Laimportanciadelossistemasoperativosnacehistricamentedesdelos50's,cuandosehizo
evidente que el operar una computadora por medio de tableros enchufables en la primera
generacinyluegopormediodeltrabajoenloteenlasegundageneracinsepodamejorar
notoriamente,pueseloperadorrealizabasiempreunasecuenciadepasosrepetitivos,locual
esunadelascaractersticascontempladasenladefinicindeloqueesunprograma.Esdecir,
secomenzaverquelastareasmismasdeloperadorpodanplasmarseenunprograma,el
cualatravsdeltiempoyporsuenormecomplejidadselellam"SistemaOperativo".As,
tenemosentrelosprimerossistemasoperativosalFortranMonitorSystem(FMS)eIBSYS.
Elresultadofueunsistemadelcualunodesusmismosdiseadorespatentizsuopininenla
portadadeunlibro:unahordadebestiasprehistricasatascadasenunfosodebrea.Surge
tambin en la tercera generacin de computadoras el concepto de la multiproceso, porque
debido al alto costo de las computadoras era necesario idear un esquema de trabajo que
mantuviesealaunidadcentraldeprocesamientomstiempoocupada,ascomoelencolado
(spooling ) de trabajos para su lectura hacia los lugares libres de memoria o la escritura de
resultados. Sin embargo, se puede afirmar que los sistemas durante la tercera generacin
siguieronsiendobsicamentesistemasdelote.
Para finales de los 80's, comienza el auge de las redes de computadores y la necesidad de
sistemasoperativosenredysistemasoperativosdistribuidos.LaredmundialInternetseva
haciendoaccesibleatodaclasedeinstitucionesysecomienzanadarmuchassoluciones(y
problemas ) al querer hacer convivir recursos residentes en computadoras con sistemas
operativos diferentes. Para los 90's el paradigma de la programacin orientada a objetos
cobra auge, as como el manejo de objetos desde los sistemas operativos. Las aplicaciones
intentancrearseparaserejecutadasenunaplataformaespecficaypoderversusresultados
en la pantalla o monitor de otra diferente (por ejemplo, ejecutar una simulacin en una
mquinacon UNIX y ver los resultados en otra con DOS ). Los niveles de interaccin se van
haciendocadavezmsprofundos.
ActualmentepodemosresumirquedetodoesteprocesohistricoseextraequeunSistema
Operativo es un conjunto de programas que controla los dispositivos que forman el
ordenador(memoriayperifricos),administralosrecursosygestionalaejecucindelresto
del software. De alguna forma acta como enlace entre el usuario y los programas y el
hardwaredelordenador.Aunqueahoralosveremosenmsdetalle,losobjetivosbsicosde
unsistemaoperativopodranresumirseendos:
Realizarunaeficientegestindelosrecursosdelordenador
Ocultarlosdetallesespecficosdefuncionamientodelosdispositivos,consiguiendo
deestaformaunciertoniveldeabstraccinrespectodelhardware.
Elobjetivofundamentaldelossistemasoperativosesgestionaryadministrareficientemente
losrecursosdeuncomputador,permitiendolaejecucindeprogramassinqueseproduzcan
conflictosenelaccesodelosrecursosutilizados,ysinqueningnprogramamonopoliceun
mediodeterminado.
Elsistemaoperativoefecta,entreotras,lassiguientesfunciones:
Desdeelpuntodevistadelusuariocomn:
Comandosparaentraryabandonarelsistema.
rdenesparamodificarlaclavedeentrada.
Comandosparadefinirlascaractersticasdeunterminal.
Establecerlasrutasdebsqueda.
Ejecucinycontroldeprogramas.
Paraestablecerprioridadesenlosprocesos.
Paralamanipulacindeficherosysubdirectorios.
Paralainformacindeestado.
rdenesdeadministracin
Desdeelpuntodevistadelprogramadordeaplicaciones:
Creacindeprocesosyborrado.
Comunicacinysincronizacindeprocesos.
Actividadesdetemporizacin.
Gestinyusoderecursos.
Asignacinyliberacindememoria.
Establecimientodeprioridades.
Desdeelpuntodevistadelaseguridaddelsistema:
248 PROGRAMACIN C++ Y COMUNICACIONES.
ProteccindeE/S:Paraconseguirlasediferenciandosmodosdeoperacin:modo
usuarioy modo supervisor. Elcambio deun modo a otro secontrolaporparte del
S.O.,siendosloposibleelcambioamodosupervisordesdeunusuariopormediode
llamadasafuncionesdelS.O.Deestemodociertasinstruccionessloseejecutarn
enmodosupervisoryelS.O.PodrcontrolarcomoserealizalaE/S.
De forma resumida podemos establecer las funciones del sistema operativo en base a los
gestoresbsicosdelosquehabitualmenteconsta:
3.GestindeE/S:Losprogramasaccedenalosperifricosdeformasencilla.
4.Gestindedispositivosdealmacenamiento:organizalainformacinenarchivosy
carpetasypermiteelaccesorpidoyeficienteadichainformacin.
Gestin de procesos
Estrategiasparalagestindeprocesos
Existendosformasbsicasdetrabajarconuncomputador:porlotesydeformainteractiva.
En esta ltima, la CPU est constantemente atendiendo al usuario, y en cualquier caso,
aunquelaCPUtengavariosprocesosenmemoria,setienelaimpresindequeelusuarioest
trabajando directamentecon elcomputador. Los primeros sistemas operativos funcionaban
como monotarea o serie; es decir, hasta que no finaliza la ejecucin de un programa no
empiezaaejecutarseotro.
Segnelsistemaoperativoenparticularsedefinendiferentesestadosparaunproceso.Los
estados bsicos son activo, bloqueado y preparado. Se dice que un proceso est en estado
activo, o de ejecucin, cuando la CPU est ejecutando sus instrucciones. Se dice que un
procesoentraenestadodebloqueocuandolaCPUnopuedecontinuartrabajandoconl,a
causadetenerqueesperaralarealizacindeunaoperacindeentrada/salida,oaalgnotro
eventodenaturalezasimilar.Sedicequeunprocesoestenestadopreparado,oejecutable,
cuandolaCPUpuedeiniciarocontinuarsuejecucin.
Enlossistemasmultitarea,cuandounprocesoentraenestadodebloqueado,unmdulodel
sistemaoperativodenominadodistribuidor(dispacher)pasaelturnodeejecucinaunode
losprocesosdelamemoriaprincipalqueestenestadopreparado.Paraello,seproduceuna
interrupcin que provoca una conmutacin de contexto entre procesos. El cambio de
contexto implica almacenar en una zona de la memoria principal toda la informacin
referente al proceso interrumpido. Esta informacin, denominada contexto de un proceso,
est referida a los contenidos de los registros de la CPU, indicadores de los biestables,
punterosaarchivosdediscos,contenidodelapila,etc.;ascomo,informacindelastablas
referentesalestadodelosprocesosenmemoria.Elcambiodecontextosuponeunconsumo
detiempodeCPUporpartedeldistribuidor.Cuandoeldistribuidorvuelvaadarelturnoal
proceso interrumpido, por haber finalizado la operacin de E/S; es decir, haber salido del
estado de bloqueado y entrado en el de preparado, debe producirse la recuperacin de
contexto en el sentido contrario al anterior, ya que, tiene que restituirse desde la zona
auxiliar de memoria los contenidos de los registros salvados, quedando la CPU tal y como
estabaenelinstantequeinterrumpiesteproceso,ypreparada,portanto,paraproseguirsu
ejecucin.Estasoperacionesocurrensucesivamenteparacadaunodelosprocesosexistentes
enmemoriaprincipal.
Eltipodemultitareadescritoanteriormente,enelqueunprocesodejadeejecutarseporla
CPUcuandoseproduceuneventorelativoaunaE/Sosimilar,tieneelinconvenientedeque
un proceso que contiene muchas operaciones de procesamiento y pocas E/S, puede
monopolizar la CPU, hasta que finalice su ejecucin. Los sistemas multitarea no
necesariamente deben esperar a que un proceso pase al estado de bloqueado para que el
250 PROGRAMACIN C++ Y COMUNICACIONES.
Unsistemamultitareadebedisponerdelastcnicasapropiadasdeproteccindememoriay
de control de concurrencias para permitir el acceso compartido a dispositivos de E/S y
archivos. Un sistema multiusuario prev el uso compartido de distintos usuarios, debiendo
resolverse cuestiones como la identificacin, autentificacin, privilegios, y control de todos
losusuarios.
Unodelosalgoritmosdeplanificacindemayorinters,porsuantigedad,sencillezyamplio
uso,eseldepeticincircular(roundrobin).Estealgoritmo,tambinllamadocooperativo,
hasidousadoporWindowsyMacintosh.Conelalgoritmodepeticincircular,acadaunode
los procesos en memoria, se le asigna un intervalo de tiempo fijo, o periodo, llamado
quantum. El objetivo de este algoritmo es cambiar de contexto de un proceso a otro, de
formarotatoria,conformesevanconsumiendosuquantum.
Enlossistemasoperativosdetiempocompartidosecambiadecontexto,noslocuandosele
acaba un quantum a un proceso, sino tambin, en el instante en que quede bloqueado; es
decir,eldistribuidorprovocaunaconmutacindecontextodelprocesoPialPjydaelturnoa
Pjsiemprequesecumplaunadelosdoscondicionessiguientes:
a) ElprocesoPiagotesuquantum.
b) ElprocesoPisebloquee.
siendoPjeselsiguienteprocesopreparadoquelecorrespondeelturno.
Laasignacindequantumsuelehacerseconayudadeungeneradordepulsossincronizado
con la frecuencia de la red de suministro de energa elctrica, 50 Hz en Europa, 60 Hz en
Estados Unidos. Transcurrido el perodo de tiempo correspondiente, 20 ms, o 16.7 ms, se
produceunainterrupcinquelanzaaejecucinelmdulogestordelrelojdetiemporeal,que
entreotrosobjetivossirvedereferenciaparagenerareltiempoasociadoalquantum.
Graficoquemuestraelcomportamientodeunsistemadeplanificacin"roundrobin"paradaratencina
procesos(AE)quesevanejecutandodeformadinmica.Ennegrosepintaelestadodeespera.
Otroalgoritmodeplanificacindeprocesoseseldeasignacindeprioridades,usadoporlos
sistemas operativos OS/2, UNIX y WindowsNT. Consiste en definir prioridades para los
procesos,pudiendoelplanificadormodificardichaprioridaddinmicamente.Eldistribuidor
da el turno al proceso preparado que tenga asignada la mayor prioridad. Existen varios
criteriosdeasignacindeprioridades;aspues,paraqueeldemayorprioridad,yportanto
activo,nomonopoliceelusodelaCPU,acadainterrupcindelrelojdetiemporealselebaja
laprioridaddelprocesoactivo.
Otros sistemas operativos de gran inters son los sistemas operativos de tiempo real. El
conceptodetiemporealhacereferenciaaqueelcomputadordebegarantizarlaejecucinde
unproceso,oobtencindeunresultadodentrodeunlmitedetiempopreestablecido.Este
tiempopuedeserpequeoogrande,dependiendodelaaplicacin.Lossistemasdetiempo
realseusanampliamenteencontrolindustrial,equiposdeconmutacintelefnicas,control
de vuelo, aplicaciones militares, simuladores, etc. Los sistemas operativos de tiempo real
debensercapacesderesponderaloseventos,ointerrupciones,quesepuedanproducirde
forma asncrona, a veces miles por segundo, en unos plazos de tiempo previamente
especificados. Frecuentemente son sistemas multitarea en los que los algoritmos de
planificacinsondeltipodederechopreferencial,conlosquesiempreseejecutalatareade
mayor prioridad y no se interrumpe hasta que finalice, a no ser que se genere otra de
prioridad mayor. El estndar POSIX tiene definidas unas extensiones de tiempo real,
establecindosediferentesnivelesderequisitos.
Estadosdeunproceso
Unproceso,desdeelpuntodevistadesuejecucin,puedeencontrarseenunade
diversassituacionesoestados,loscualesserepresentanesquemticamenteenlafigura9.1.
La mayora de ellos ya han sido analizados anteriormente, por lo que se resumirn muy
brevemente. Adems, cada sistema operativo implementar un determinado conjunto de
estados y unas condiciones de paso de un estado a otro, por tanto el funcionamiento aqu
descrito pretende ser una referencia para la comprensin de la problemtica relativa a la
gestin de procesos. Un proceso nonato es aquel que no ha iniciado su ejecucin. Un
ejemploesunprogramaretenidoenunacolaesperandoaqueelplanificadordetrabajosyel
distribuidorledenpasoaejecucin.
Delestadodebloqueadosepuedepasaralestadopreparadocuandoacabalaoperacinde
E/Spendiente,oseleasignaelrecursoesperado.Tambin,esnecesariotenerencuentaque
algunossistemasoperativosrealizanintercambioentrelamemoriaprincipalyeldisco,locual
lespermitelaejecucinconcurrentedemsprocesosdelosqueadmitelamemoriaprincipal,
ya que un proceso puede ser trasvasado a disco, definindose por tanto el estado de
bloqueadointercambiado,obloqueadoendisco.Unejemplodeprocesobloqueadoesaquel
quesolicitaaloperadordelcomputadormontarunadeterminadacintay,sinohaymemoria
suficienteparalosotrostrabajosenprogreso,lotrasvasaadisco.Silacargadeprocesoses
grande,inclusolosprocesospreparadospuedentrasvasarseadisco,pasandoasalestadode
preparadointercambiadoopreparadoendisco.
Cuandodesdeunterminalinteractivoseactivalacomunicacinconelcomputador,oseleda
la vez a un proceso de la cola serie, el proceso correspondiente entra en estado de
preparado, desplazndose por los estados del diagrama de la figura 9.1. Cuando finaliza la
ejecucin de un proceso o se detecta un error grave en l, el proceso pasa a estado de
muerto,liberandoelsistemaoperativolazonadememoriaqueocupaba.
Gestin de la memoria
Enlossistemasoperativosdemonoprogramacinlamemoriaprincipalsepuedeorganizarde
diversasmaneras.Elsistemaoperativopuedeocuparlasprimerasposicionesdememoria,o
lasltimas,oinclusopartedelsistemaoperativopuedeestarenlazonaRAMdedirecciones
bajas,yotrapartedel,comosonlosgestoresdeperifricos,oelcargadorinicial,pudieran
encontrarseenROMenlasdireccionesaltas.Estaltimasituacinsecorrespondeconlade
los antoguos PCs compatibles, en los que la ROM contiene el sistema bsico de entradas y
salidasoBIOS(BasicInputOutputSystem,SistemaBsicodeEntradasySalidas).
Encualquiercaso,cuandoelusuariodaunaorden,sielprocesoquelaimplementanoesten
memoria, el intrprete de comandos del sistema operativo se encarga de cargarlo en
memoriadesdedisco,yeldistribuidordapasoasuejecucin.Cuandofinalizaelproceso,el
sistema operativo visualiza el indicador de peticin de orden y espera a que se le d una
nueva orden, en cuyo caso libera la zona de memoria ocupada, sobreescribiendo el nuevo
programasobreelanteriorproceso.
Enunsistemademultiproceso,cuandounprogramasecargaenmemoriaparaserejecutado,
ocontinuarsuejecucin,elsistemaoperativoleasignaunadireccinbase,deacuerdocon
losespacioslibresdememoria,ytransformadireccionesvirtualesendireccionesfsicas.Estas
transformacionessuelenserefectuadasporcircuitosespecializadosqueconstituyenlaMMU
(MemoryManagementUnit,UnidaddeGestindeMemoria),queenlaactualidadsesuele
integrarenelmismochipdelaCPU.
Particionesestticas.
Particionesdinmicas.
Paginacin.
Segmentacin.
Memoriavirtual.
Particionesestticas
lasdireccionesdecomienzodecadaparticin.Eltamaodelaparticinesdeterminadopor
eloperadoroporelsistemaoperativo.Tamaosusualesson8K,16K,32K,o64K.
El sistema operativo mantiene una tabla en la que cada fila corresponde a una
particin, conteniendo la posicin base de la particin; su tamao, no todas las particiones
tienenporquseriguales;yelestadodelaparticin,ocupadaonoocupada.Elplanificador
de trabajos, una vez que una particin est libre, hace que se introduzca el programa de
mximaprioridadquehayaenlacoladeesperayquequepaendichaparticin.Sielespacio
deunaparticinesmpalabrasyelprogramaocupanposiciones,severificarsiempreque:n
m.
Particionesdinmicas
Lautilizacindeparticionesdinmicassebasaenquelosprogramassonintroducidosporel
sistema operativo inicialmente en posiciones consecutivas de memoria, no existiendo, por
tanto,particionespredefinidas.Elsistemaoperativopuedegestionarelespaciodememoria
usando una tabla de procesos, en la que cada lnea contiene el nmero de proceso o
identificativo del mismo, el espacio que ocupa y la direccin base. Existe una tabla
complementariaalaanteriorconlosfragmentosohuecoslibres.Elplanificadordetrabajos
peridicamente consulta la tabla, introduciendo en memoria los programas que quepan en
losfragmentos.
Al iniciarse una sesin de trabajo se carga el primer programa, dejando un fragmento libre
donde se pueden incluir otros programas. Al finalizarse los procesos, el nmero de
fragmentoscreceryelespaciodisminuir,llegandounmomentoenqueelporcentajede
memoria aprovechado es muy reducido. El problema puede resolverse haciendo una
compactacin. Esta consiste en agrupar todos los fragmentos cuandoacaba la ejecucin de
un proceso, quedando as slo uno grande. La compactacin se efecta reubicando los
procesosenejecucin.
Paginacin
Conesteprocedimientolamemoriaprincipalseestructuraenmarcosdepginasdelongitud
fija,tambindenominadosbloques,quesuelenserde512bytes,1Kbytes,2Kbytes,4Kbytesu
8 Kbytes. De esta forma,por ejemplo, la memoria de uncomputadorde 256Kbytespodra
quedar dividida en 64 marcos de pgina de 4Kbytes cada uno. Cada marco de pgina se
identificaconunnmerocorrelativo,enelcasoanteriorde0a63.Asimismo,losprocesosde
256 PROGRAMACIN C++ Y COMUNICACIONES.
Elfundamentodelapaginacinresideenquenoesnecesarioqueunprocesosealmaceneen
posicionesconsecutivas dememoria. Las pginas se almacenan enmarcos depgina libres,
independientemente de que estn o no contiguos. Cada marco de pgina contiene
instrucciones consecutivas. Una instruccin de un proceso se localiza dando el nmero de
marco y la direccin relativa dentro de l. El sistema operativo, en lugar de mantener una
tabladeprocesos,comoenelcasodeparticionesdinmicas,mantienetrestiposdetablas:
1.Tabladelmapadememoria.Contienetantasfilascomomarcosdepgina.Seindica
elidentificadordelprocesoqueestencadabloquey,ensucaso,siestlibre.
3.Tabladelmapadepginas.Hayunaporproceso,ycontieneennmerodemarco
dondeseencuentracadaunadesuspginas.Lalongituddecadatablaesvariable,
dependiendo del nmero de pginas; es decir, depende del tamao de cada
proceso.
LastablasdepaginacinotablasdepginassonunaparteintegraldelSistemadeMemoria
Virtual en sistemas operativos, cuando se utiliza paginacin. Son usadas para realizar las
traducciones de direcciones de memoria virtual (o lgica) a memoria real (o fsica) y en
generalelsistemaoperativomantieneunaporcadaprocesocorriendoenelsistema.
Encadaentradadelatabladepaginacin(eninglsPTE,Page TableEntry)existeunbitde
presencia, que est activado cuando la pgina se encuentra en memoria principal. Otro bit
que puede encontrarse es el de modificado, que advierte que la pgina ha sido modificada
desdequefuetradadeldisco,yporlotantodeberguardarsesieselegidaparaabandonar
la memoria principal; y el bit de accedido, usado en el algoritmo de reemplazo de pginas
llamado Menos Usado Recientemente (LRU, least recently used). Tambin podran haber
otrosbitsindicandolospermisosquetieneelprocesosobrelapgina(leer,escribir,ejecutar).
Dado que las tablas de paginacin pueden ocupar un espacio considerable de la memoria
principal,estastambinpodranestarsujetasapaginacin,loquedalugaraunaorganizacin
paginadademltiplesniveles(otabladepginasmultinivel).Enlossistemasconuntamao
de direcciones muy grande ( 64 bits ), podra usarse una tabla de pginas invertida, la cual
utilizamenosespacio,aunquepuedeaumentareltiempodebsquedadelapgina.
LastablassonmantenidasporelsistemaoperativoyutilizadasporlaUnidaddeGestinde
Memoria (MMU) para realizar las traducciones. Para evitar un acceso a las tablas de
paginacin, hay un dispositivo llamado Buffer de Traduccin Adelantada (TLB, Translation
LookasideBuffer),acelerandoelprocesodetraduccin
Segmentacin
La gestin de los segmentos la realiza el sistema operativo, como con las particiones
dinmicas, slo que cada particin no corresponde a un proceso sino a un segmento. El
sistemaoperativomantieneunatablaconlossegmentosdeunproceso,deformasimilarala
de pginas. Como el tamao de los segmentos es variable, antes de realizar un acceso a
memoria se comprueba que el desplazamiento no supere al tamao del segmento, para
protegerlaszonasdememoriaocupadasporotrosegmento.
Lasegmentacinpermitequeciertosprocesospuedancompartircdigo,rutinas,odatos,sin
necesidaddeestarduplicadosenmemoriaprincipal.Aspues,siseisusuariosestnutilizando
interactivamente un procesador de textos determinado, no es necesario que estuviesen
cargadasenmemoriaseiscopiasidnticasdelcdigodelprogramaprocesadordetextos.El
cdigodelprogramaestaraunasolavez,yelsistemaoperativoselimitaraaanotarenlas
tablasmapasdesegmentosdecadaunodelosprocesosladireccindondeseencuentrael
cdigo. Por tanto, en un momento dado, en memoria existiran: segmentos asignados a
trabajosconcretos,segmentoscompartidos,ybloqueslibresdememoria.
Memoriavirtual
Lamemoriavirtualpermitealosusuarioshacerprogramasdeunacapacidadmuysuperiora
laquefsicamentetienelamemoriaprincipaldelcomputador.Enrealidad,lamemoriavirtual
haceposiblequelacapacidadmximadelosprogramasestlimitadaporelespacioquesele
258 PROGRAMACIN C++ Y COMUNICACIONES.
reserveendisco,ynoporeltamaodelamemoriaprincipal.Endefinitiva,lossistemascon
memoria virtual presentan al usuario una memoria principal aparentemente mayor que la
memoriafsicareal.
Porotraparte,lamemoriavirtualpermiteaumentarelnmerodeprocesosenlamemoria
principal en ejecucin concurrente, ya que con ella slo es necesario que est en memoria
principal untrozo mnimo de cada proceso,yno elproceso completo. Para lagestinde la
memoriavirtualsueleutilizarsealgunadelasanteriorestcnicasdegestindelamemoria:
gestindememoriaporpginas,
gestindememoriasegmentada,
gestindememoriasegmentadapaginada.
Enunsistemadememoriavirtualsemantieneendiscounarchivoconlaimagendelproceso
completo,queesttroceadoenpginasosegmentos,dependiendodelmtodo.Encambio,
enlamemoriaprincipalnicamentedebeestarlapgina,osegmento,queenesemomento
deba estar enejecucin, intercambindosepginas entredisco y memoria principal cuando
seanecesario,locualseconoceporswapping.
Lagestindememoriavirtualsegmentadaesmscomplejaqueladeltipodepaginacin,ya
que,lossegmentossondetamaovariableysonmsdifcilesdegestionar.Laspginas,por
el contrario, son de capacidad constante y preestablecida. Por ello, lo habitual es utilizar
gestindememoriaporpaginacinoporsegmentospaginados.
Lamemoriavirtualconpaginacincombinalastcnicasdepaginacineintercambio.Porlo
general, se utiliza un mtodo de intercambio perezoso (lazzy swapper), nicamente se
lleva a memoria una pgina cuando es necesaria para algn proceso, de esta forma, el
nmerodeprocesosenejecucinconcurrentepuedeaumentar.
Unodelostemasdemayorintersparaeldiseodelsistemadegestindememoriavirtual
eslabsquedadealgoritmoseficientesparadecidirqupginadebesustituirseencasode
fallo de pgina, ya que cada fallo de pgina supone una prdida de tiempo de la CPU, que
puede hacer disminuir considerablemente la productividad del computador incluso aunque
todalagestinserealiceconhardwareespecfico.Elalgoritmodescritoenelprrafoanterior,
queutilizancampodenmerosdereferencias,esdeltipoLRU.Losalgoritmosmsconocidos
sonlossiguientes:
FIFO(Firstinfirstout,PrimeroenEntrarPrimeroenSalir).Sebasaensustituirla
pginaquellevemstiempoenmemoria
LRU(LeastRecentlyUsed,ltimoRecientementeUsado).Enestecasosesustituye
lapginamenosrecientementeusada.Sebasaenelprincipiodelocalidadtemporal,
yaque,suponequelapginautilizadahacemayortiempoesmenosprobablequese
useprximamente.
NRU(NoRecentlyUsed,NoRecientementeUsado).Unadelasmltiplesformasde
implementar este tipodealgoritmo consiste enutilizar unbit de referencia que se
ponea1cadavezqueseusalapgina.Unpunterorecorrecircularmentelatablade
marcos de pgina. Inicialmente, el puntero est detenido en un marco de pgina,
cuando se tiene que desalojar una pgina analiza el bit de referencia del marco al
que apunta, si es 1, lo pone a 0 y avanza apuntando a los siguientes procesos,
cambiandolosbitsdereferenciade1a0,hastaqueencuentreunapginaconelbit
dereferenciaa0,encuyocasolaeliminadelamemoriaysedetieneenlaposicin
siguientedelatabla,hastaquesenecesitedesalojarunanuevapgina.
Se comprende mejor como acta el software de E/S utilizando un modelo conceptual por
capas.Elnivelinferioreselhardware,queeselquerealmenteejecutalaoperacindeE/S,y
el nivel superior los procesos de los usuarios. Resumidamente, las funciones de cada nivel
sonlasqueseindicanenlafigura9.2.
1. Dispositivosasignados.Consisteenasignarciertosdispositivosaunprocesodurante
la duracin del trabajo; por ejemplo, un teclado, una impresora, una lectora de
tarjetas.
ElsistemaqueimplementadispositivosdeE/Svirtualessesueledenominarspooler
(SimultaneousPeripheralOperationsOnLine,OperacionesSimultneasSobrePerifricosEn
Lnea).Laideadelgestordedispositivosvirtualesseaplicaaperifricoslentos,yconsisteen
interponer entre el proceso y el perifrico lento un dispositivo de memoria auxiliar rpido.
Usualmente, el perifrico lento es una impresora, un registrador grfico, etc., y el rpido
podraserundisco.Seobservaquelosmdulosspoolhacenquelosprocesostrabajencon
losperifricosdeE/Scomoarchivosendisco,aprovechndosedelasmejoresprestacionesde
este tipo de perifrico. Puede decirse que el disco se comporta como si se tratara de un
dispositivodeE/Stipodigitalizadoroimpresora,esdecir,eldiscosoportadispositivosdeE/S
virtuales.
Elsiguienteniveleseldegestindeperifricos,cadatipodeperifricotieneunas
caractersticas propias y va conectado a travs de un controlador fsico. Cada perifrico es
utilizado por un programa gestor, que se encarga de programar el controlador y traducir
peticiones abstractas del nivel de software independiente del dispositivo a cdigo
directamenteinterpretableporelhardware,yenviarloaunalistadepeticiones.Porejemplo,
enelcasodeunaunidaddedisco,alpresentarseelgestorcorrespondienteaunaoperacin
deleerunsector,elgestordebecomprobarsieldiscoestarrancado,posicionarelbrazoen
elcilindrocorrespondiente,inicializarelcontroladordeDMA,transmitirelmarcodepgina
de informacin, etc. En realidad, los gestores de perifricos son los nicos programas que
debentenerencuentalaspeculiaridadesconcretasdelosdispositivos.
Comoejemploparticular,enelcasodeundiscoparaconseguirmayoresvelocidades
es habitual leer fsicamente cilindros completos, en lugar de sector a sector. Una vez
localizadoelcilindrosepuedeleerelcilindrocompletoalavelocidadderotacindeldisco.La
informacin del cilindro se almacena en la cach de disco de forma que si el programa del
usuario ordena la lectura sucesiva de sectores de un mismo cilindro, cosa muy probable a
causadelalocalidadespacialdelosdatos,nosetendrnqueconsumirtiemposadicionales
delatenciaparaaccederalosdistintossectores.Estatcnicaesimplementadaporelnivelde
gestordelperifricooinclusopuedeserincluidaenelnivelhardware,elcontroladordedisco
puedeincluirlamemoriacach.NoseincluyeenelniveldesoftwaredeE/Sindependiente,
yaquesteconsideraaldiscocomounconjuntosucesivodebloques.
Elsiguienteeselniveldegestindeinterrupciones.Esteeselniveldesoftwarede
E/Squeestencontactodirectoconelhardware.CuandounprocesotieneunaE/Sseinicia
laoperacin,pasaalestadodebloqueado,yesperahastaqueacabelaoperacindeE/S.En
lamayoradelosdispositivosdeE/Slasoperacionesdelecturayescrituraseinicianyfinalizan
por medio de interrupciones. Cuando se produce la interrupcin final un proceso debe
cambiarelestadodelprocesoquehafinalizadolaoperacindeE/S;portanto,dichoproceso
pasar de bloqueado a preparado. Los gestores de interrupciones son pequeos
procedimientos que gestionan y lanzan la ejecucin de los programas correspondientes al
nivelinmediatosuperior.
Gestin de archivos.
Unarchivopuedeestructurarseendistintossoportesfsicos,dependiendodelusoo
capacidadquevayaatener.Sedistingueentreunnivelfsico,msomenosComplejo,ynivel
lgico,queproporciona una utilizacin adecuada para el usuario. El sistema operativo hace
posibleutilizarestaltima,haciendodeinterfazentrelosdos.Enefecto,desdeelpuntode
vista hardware, para almacenar datos o programas slo existen direcciones fsicas. En un
262 PROGRAMACIN C++ Y COMUNICACIONES.
Gestindearchivos
Debensercapacesdecontenergrandescantidadesdeinformacin
Suinformacindebepermanecerysobreviviralosprocesosquegeneranoutilizan
Dependiendo del sistema operativo se pueden hacer unas u otras operaciones con los
archivos.Cadaarchivousualmentecontienenombre,atributos,ydatos.Losatributospueden
incluircuestionestalescomofechayhoradecreacin,fechayhoradelaltimaactualizacin,
bits de proteccin, contrasea de acceso, nmero de bytes por registro, capacidad mxima
delarchivoycapacidadactualmenteocupada.
Lista de enlaces: Cada disco dispone de una tabla con tantos elementos como
bloques fsicos, la posicin de cada elemento se corresponde biunvocamente con
cadabloque,ycontieneelpunterodellugardondeseencuentraelsiguientebloque
delarchivo.Cuandoseabreunarchivoelsistemadearchivossecargaenlamemoria
principal la lista de enlaces, pudindose obtener rpidamente las direcciones,
usualmente 3 bytes, de los bloques consecutivos del archivo. Presenta el
Inodos:Correspondealaformadegestionarlosarchivosporelsistemaoperativo
UNIX.Cadaarchivotieneasociadounnododendices,oinodo,queesunapequea
tabla de tamao fijo conteniendo los atributos del archivo y las direcciones de un
nmero determinado de los primeros bloques del archivo. Los tres ltimos
elementos de la tabla indican indirectamente las siguientes direcciones de los
bloquesdelarchivo.
EstodalugaraunaseriedeestndaresdegestindearchivosenlosquecabedestacarFAT,
NTFSyEXT:
SistemaFAT32
Tabla de asignacin de archivos, comnmente conocido como FAT (del ingls file allocation
table),esunsistemadearchivosdesarrolladoparaMSDOS,ascomoelsistemadearchivos
principaldelasedicionesnoempresarialesdeMicrosoftWindowshastaWindowsMe.
FATesrelativamentesencillo.Acausadeello,esunformatopopularparadisquetesadmitido
prcticamente por todos los sistemas operativos existentes para computadora personal. Se
utiliza como mecanismo de intercambio de datos entre sistemas operativos distintos que
coexistenenlamismacomputadora,loqueseconocecomoentornomultiarranque.Tambin
seutilizaentarjetasdememoriaydispositivossimilares.
LasimplementacionesmsextendidasdeFATtienenalgunasdesventajas.Cuandoseborrany
seescribennuevosarchivostiendeadejarfragmentosdispersosdestosportodoelsoporte.
Con el tiempo, esto hace que el proceso de lectura o escritura sea cada vez ms lento. La
denominada desfragmentacin es la solucin a esto, pero es un proceso largo que debe
repetirseregularmenteparamantenerelsistemadearchivosenperfectascondiciones.FAT
tampoco fue diseado para ser redundante ante fallos. Inicialmente solamente soportaba
264 PROGRAMACIN C++ Y COMUNICACIONES.
nombres cortos de archivo: ocho caracteres para el nombre ms tres para la extensin.
Tambin carece de permisos de seguridad: cualquier usuario puede acceder a cualquier
archivo.
FAT32fuelarespuestaparasuperarellmitedetamaodeFAT16almismotiempoquese
mantena la compatibilidad con MSDOS en modo real. Microsoft decidi implementar una
nuevageneracindeFATutilizandodireccionesdeclusterde32bits(aunqueslo28deesos
bitsseutilizabanrealmente).
FAT32apareciporprimeravezenWindows95OSR2.Eranecesarioreformatearparausar
las ventajas de FAT32. Curiosamente, DriveSpace 3 (incluido con Windows 95 y 98) no lo
soportaba. Windows 98 incorpor una herramienta para convertir de FAT16 a FAT32 sin
prdida de los datos. Este soporte no estuvo disponible en la lnea empresarial hasta
Windows2000.
EltamaomximodeunarchivoenFAT32es4GiB(2321bytes),loqueresultaengorroso
para aplicaciones de captura y edicin de video, ya que los archivos generados por stas
superanfcilmenteeselmite.
SistemadeficherosNTFS
NTFS (del ingls New Technology File System) es un sistema de archivos de Windows NT
incluido en las versiones de Windows 2000, Windows XP, Windows Server 2003, Windows
Server2008,WindowsVista,Windows7yWindows8.Estbasadoenelsistemadearchivos
HPFS de IBM/Microsoft usado en el sistema operativo OS/2, y tambin tiene ciertas
influenciasdelformatodearchivosHFSdiseadoporApple.
NTFS permite definir el tamao del clster a partir de 512 bytes (tamao mnimo de un
sector)deformaindependientealtamaodelaparticin.
Suprincipalinconvenienteesquenecesitaparasmismounabuenacantidaddeespacioen
discoduro,porloquenoesrecomendablesuusoendiscosconmenosde400MiBlibres.
LosnombresdearchivosonalmacenadosenUnicode(UTF16),ylaestructuradeficherosen
rbolesB,unaestructuradedatoscomplejaqueaceleraelaccesoalosficherosyreducela
fragmentacin,queeralomscriticadodelsistemaFAT.
SistemasEXT(Linux)
ActualmenteseutilizalacuartaversindeestesistemadeficherosutilizadoporLinux.ext4
(fourth extended filesystem o cuarto sistema de archivos extendido) es un sistema de
archivostransaccional(eninglsjournaling),anunciadoel10deoctubrede2006porAndrew
Morton, como una mejora compatible de ext3. El 25 de diciembre de 2008 se public el
kernelLinux2.6.28,queeliminayalaetiquetade"experimental"decdigodeext4. Utilizaun
rbolbinariobalanceado(rbolAVL)eincorporaelasignadordebloquesdediscoOrlov.
SistemasHFS(MacOS)
HFSPlusoHFS+esunsistemadearchivosdesarrolladoporAppleInc.parareemplazaralHFS
(Sistemajerrquicodearchivos).TambineselformatousadoporeliPodalserformateado
desdeunMac.
Los volmenes de HFS+ estn divididos en sectores (bloques lgicos en HFS), de 512 Bytes.
Estos sectores estnagrupados juntos enunbloque deasignacin que contieneuno o ms
sectores;elnmerodebloquesdeasignacindependedeltamaototaldelvolumen.HFS+
usaunvalordedireccinparalosbloquesdeasignacinmayorqueHFS,32bitfrentea16bit
de HFS; lo que significa que puede acceder a 232 bloques de asignacin. Tpicamente un
266 PROGRAMACIN C++ Y COMUNICACIONES.
volumen HFS+ esta embebido en un Envoltorio HFS (HFS Wrapper), aunque esto es menos
relevante. El envoltorio fue diseado para dos propsitos; permitir a los ordenadores
MacintoshHFS+sinsoporteparaHFS+,arrancarlosvolmenesHFS+yayudaralosusuariosa
realizar la transicin a HFS+. HFS+ arrancaba con un volumen de ficheros de solo lectura
llamadoWhere_have_all_my_files_gone?,queexplicabaalosusuariosconversionesdelMac
OSsinHFS+,queelvolumenrequiereunsistemaconsoporteparaHFS+.Elvolumenorigina
HFS contiene una firma y un desplazamiento en los volmenes HFS + embebidos en su
cabeceradelvolumen.TodoslosbloquesdeasignacinenelvolumenHFSquecontienenel
volumenembebidosonmapeadosfueradelarchivodeasignacinHFScomobloquesdaados
Gestindedirectorios
Lasegundaabstraccinqueutilizaelsistemaoperativoparagestionarvolmenesde
datos es la de directorio. Los directorios son conjuntos de archivos agrupados, siguiendo
algn criterio: directorio del usuario que lo crea, directorio de cartas, directorio de
aplicaciones,etc.Laestructuraglobaldelsistemadearchivossueleorganizarseenformade
rbol en el que los nodos interiores son directorios, o archivos, y los nodos exteriores son
archivos. De un directorio pueden depender archivos u otros directorios, tambin
denominadossubdirectorios.
Un directorio se gestiona con una tabla de ndices, que contiene un elemento por
cadaarchivoodirectoriodependientedel.Cadaelementoestformadoporelnombredel
archivodadoporelusuario,yporinformacinadicionalutilizadaporelsistemaoperativo.La
informacin adicional sobreel archivo puede estar constituida por losatributos y elbloque
dondecomienzaelarchivo,casodeMSDOS.Tambin,lainformacinadicionalpuedeserun
punteroaotraestructuraconinformacinsobreelarchivo.EsteeselcasodeUNIX,enelque
el puntero sencillamente es la direccin del inodo del archivo, que contiene tanto los
atributosdelarchivocomolatabladeposiciones.
ElBIOSdelDOS
El BIOS (Basic Input Output System, Sistema Bsico de Entradas y Salidas) del DOS se
encuentraenunarchivo,queenelPCDOSdeIBMsellamaIBMIO.SYS;yqueenMSDOSse
llamaIO.SYS.EstearchivoseencuentraentodoslosPCcomoprimerarchivoeneldirectorio
raz del disco de arranque, y est equipado con los atributos de archivo HIDDEN y SYSTEM,
paraquenoaparezcaenlapantallaconlallamadadelcomandoDIR.
CuandoDOSquierecomunicarseconalgunodeestosdispositivosutilizaloscontroladoresde
dispositivoscontenidosenesemdulo,queasuvezempleanlasrutinasdelROMBIOS.Slo
elBIOSdelDOSyloscontroladoresdedispositivosentranencontactoconelhardware,esto
hacequeestosseanloselementosmsdependientesdelhardware.Enlasprimerasversiones
estapartedelDOSdebaseradaptadaporlosdiferentesfabricantesdehardware,debidoa
quelasdiferenciasentrelosPCdediferentesfabricanteseransignificativas.
ElncleodelDOS
ElncleodelDOS,tambinconocidoporsudenominacininglesaKernel,seencuentraenel
archivo IBMDOS.SYS en el PCDOS, o en el archivo MSDOS.SYS para MSDOS. Se encuentra
inmediatamentedespusdelarchivoIMBIO.SYS,oIO.SYS,eneldirectoriorazdelaunidadde
arranque.Aligualqueelanteriorarchivonoesvisibleporelusuario,yaquellevalosatributos
dearchivoSYSTEMyHIDDEN;adems,aligualquesupredecesor,nosepuedeborrarporque
ademssemarcconelatributoREADONLY.
EnestearchivoseencuentralasinnumerablesfuncionesdelDOSAPI,quesepuedenalcanzar
atravsdelainterrupcin21h.Todaslasrutinasestndiseadasdeformaindependientedel
hardware,yseutilizanparaelaccesodeotrosdispositivosdelBIOSdelDOS.Porestarazn,
estemdulonosehadeadaptaralhardwaredelosdiferentesordenadores.
Elprocesadordecomandos
Al contrario que en el caso de los dos mdulos presentados hasta ahora, el procesador de
comandos del DOS, denominado SHELL, se encuentra en un archivo visible con el nombre
COMMAND.COM.Esteeselprogramaquesellamaautomticamenteduranteelarranquedel
ordenador.Muestraelprompt(smbolodelalneadecomandos)delDOSenlapantalla(A>
oC>).Sufuncinprincipalesprocesarlassucesivasentradasdelusuario.
270 PROGRAMACIN C++ Y COMUNICACIONES.
ElprocesadordecomandoseselnicocomponentevisibledelDOS,demodoqueenalgunos
casos es errneamente considerado como el sistema operativo en s. En realidad, slo un
programanormal,quefuncionabajoelcontroldelDOS.Elprocesadordecomandosnoessin
embargo un bloque monoltico, sino que se encuentra dividido en tres mdulos, una parte
residente,unapartenoresidente,ylarutinadeinicializacin.
Lapartenoresidentecontieneelcdigodelprogramaparalasalidadelindicadordelsistema,
paraleerlasentradasdeusuariodeltecladoyparasuejecucin.Elnombredeestemdulo
sedebeaquepuedesersobrescritoporlosprogramasdeusuario,yaque,seencuentraenla
partesuperiordelamemoria,porencimadeestosprogramas.Peroestonoimporta,yaque
traslaejecucindeunprogramasevuelveapasaralaparteresidente.Estecompruebasila
parte noresidente fue sobrescrita, y la vuelve a cargar de la unidad de arranque, si fuera
necesario.
Lapartedeinicializacinsecargaduranteelarranquedelcomputador,yacogelastareasde
inicioelsistemaDOS.Cuandofinalizasutrabajo,yanoesnecesaria,ysepuedesobreescribir
porotroprograma.
Cuando aparecieron las primeras versiones de Windows hacia el ao 1986, tanto desde el
punto de vista del usuario, como del programador aparecieron unas prestaciones muy
limitadas.Enesencia,setratabadeunacapaqueseestablecaencimadelDOSycuyasnicas
ventajaseransusistemagrfico;laindependenciadelosdispositivos,esdecir,delhardware;
yunamultitareacooperativaentrelasescasasaplicacionesqueexistan.Enloreferenteala
presentacin,sepuededecirqueaquellaprimeraversineramuysimple.
EnpocosaosMicrosoftlanzunanuevasagaderevisionesbajolaversin2.0,conunlavado
de cara y una mayor eficacia en el cdigo, pero es en la versin 3.0 donde el impacto de
Windowsrompetodaslasprevisiones.Porprimeravez,Windowsaprovechabaporcompleto
de la arquitectura 80386 para construir un sistema de memoria virtual de forma que sta
podaextendersehastacuatroveces,siempreycuandoexistiesesuficienteespacioeneldisco
duro.LasventasinicialesdeWindows3.0fueronespectaculares.
Unaventanacompletaestconstituidaporuntrozodepantalla,habitualmenteconunttulo,
enelqueapareceenlapartesuperiorizquierdaunmengeneralconformadebotn,quese
despliega al pulsarlo. En la derecha existen otros botones que permiten actuar sobre el
tamaodelaventana.Estosltimostienenlaposibilidaddemaximizar,laventanaocupar
toda la pantalla; o minimizar la ventana, pasando a ocupar la mnima extensin,
convirtindoseenunicono.Adicionalmente,laventanapuedeserredimensionadapinchando
elbordedelamismaconelratn,deformaquealarrastrarlosemodificasutamao.Para
moverla,sepinchasobrelabarradelttuloysearrastralaventanaalaposicinrequerida.
Segnloexpuesto,eltamaodelasventanasesmuyvariableylainformacinquecontienen
puede no ser presentable toda a un tiempo. Aqu entra en juego la figura de las barras de
desplazamiento,encargadasdemoverelcontenidodelaventanasobreunespaciodetrabajo
queseconsideramsamplio.
EnsusprimerasversionesWindowsadmiaetresmodosdeejecucin:real,sloversin3.0;
estndar; y mejorada. En los dos ltimos se rompe la barrera de los 640k que tena
antiguamente el DOS, aprovechando toda la memoria que consiga almacenar nuestro
ordenador. La diferencia entre el modo estndar y el mejorado se traduce en un diferente
aprovechamiento de la memoria. El modo mejorado requiere disponer de al menos un
microprocesador80386y2MbytesdememoriaRAM.Lasventajasdeestemodoseapoyan
ms que nada en la existencia de un modo virtual de memoria que permite cuadruplicar la
cantidaddememoriavisibleparalasaplicaciones,graciasalautilizacindelespacioexistente
en el disco duro. Ms adelante, cuando se hable sobre el Panel de Control se ver el lugar
precisodondeconfigurarestaposibilidad.
Conlaversin3.0deWindowsaparecieronunaseriedeaplicacionesquecambiaron
significativamente la actuacin sobre un computador, estos elementos que en la actualidad
hansidomejoradospermitieronunainterfazmsamigableconelordenador.Loselementos
que se describen a continuacin permiten cierto control sobre la configuracin del sistema
operativo,yensumomentorepresentaronungranavanceparalagestindellosrecursosdel
computador.Losprincipalescomponenteseran:
Administradordeprogramas.Estaaplicacin,aunquesetratadeunprogramams,
tiene la peculiaridad de ser el primero en cargarse en memoria y permanecer
siempreresidente.Sufuncinprincipalespermitirlaeleccinyposteriorejecucin
de otras aplicaciones, de una forma organizada. El administrador de programas
permiteiniciarfcilmentelasaplicacionesyorganizarlosarchivosylasaplicaciones
engruposlgicos.
quepuedeemplearseparalaorganizacinyutilizacindearchivosydirectorios.Las
operaciones bsicas que se pueden realizar sobre los disquetes y discos duros son
hacerunduplicadodeldisco,formatearlo,ydarleunnombredevolumen.
Elpaneldecontrolesunprogramaqueincluyeunaseriedecomponentesquesirven
para ajustar la configuracin del sistema. El panel de control es una aplicacin
Windows que permite modificar de forma visual las caractersticas del sistema
durantelautilizacindeWindows.Cadaunadelasopcionesquepuedenmodificarse
aparece representada con el icono correspondiente en la ventada del Panel de
control. Las opciones existentes son las siguientes: los colores de la pantalla, otras
opciones del Escritorio que determinan el aspecto de la pantalla, las fuentes que
reconocernlasaplicacionesdeWindows,lasimpresorasutilizadas,losparmetros
deltecladoydeldispositivoapuntador(ratn),lasopcionesinternacionales,puertos
y redes, la fecha y hora del sistema, los sonidos que utilizar el sistema, los
parmetros MIDI que utilizar el sintetizador conectado a la computadora, y
finalmente las opciones de multitarea para la ejecucin de Windows en el modo
extendidodel80386.
ElprotocoloDDEestorientadoalintercambiodinmicodedatosquepermiteque
lasaplicacionesdeWindowspuedanintercambiarinformacinyactuarenbaseaelladeuna
forma totalmente cooperativa. Bajo DOS, cada programa se comporta como una isla en
medio de un ocano, obligando al programador a hacer ingeniosos esfuerzos cuando dos
aplicacionesnecesitancompartirdatos.Aunquesudiseoestorientadoalaejecucindeun
nicoprograma,esposibleobtenermultitareadejandoprogramasresidentesenmemoria.El
problemadelacomunicacinnoparecetalcuandounaaplicacingeneraunarchivodesalida
queotrapuedeleer,aunquenosetratedeunverdaderointercambiodeinformacin,dado
274 PROGRAMACIN C++ Y COMUNICACIONES.
quelasaplicacionesdifcilmentepuedenmantenerelcontrolsobreenqumomentosedebe
enviarorecibirlainformacin.Paraquedosaplicacionespuedanaccederareasdememoria
comunesnormalmenteseutilizaninterrupcionesquesoninstaladasamododeinterfaces.Las
aplicaciones que intervienen tienen que estar de acuerdo en la forma de acceder a las
interrupciones y en el formato de los datos sin que el DOS provea de ningn mecanismo
prcticoparallevaracabolatarea.
ProtocoloOLE(ObjectLinkedandEmbeddedObjetoUnidoyEmbebido)
Antelagranimportanciadelintercambiodeinformacinentreaplicaciones,sedesarrollun
nuevoprotocolodenominadoOLE,quehizosuaparicinenlaversin3.10.ElOLE,enlneas
generales,estableceunmtodoestndarparaquedistintasaplicacionespuedanenlazary
compartirsusdocumentos.Setienendosconceptosnuevos:eldeobjetocomoconjuntode
datos;yeldedocumento,ocontenedor,dondesepuedenalmacenarlosobjetosUnobjeto,
porejemploundibujo,tieneunnicopropietarioqueeslaaplicacinquelocre,peropuede
tenermltiplesdestinos,esdecir,serutilizadopordistintasaplicaciones.
El protocolo OLE est basado en mensajes que establece una conversacin entre cliente y
servidor, informando acerca de los objetos: aplicacin origen, formatos, cambios en los
mismos, solicitud de actualizaciones, etc. OLE implica ciertos cambios en la mayora de los
programas, con el fin de que lo puedan gestionar y dejen de considerar como exclusiva la
informacin que manejas. A nivel de usuario OLE utiliza comandos a los que ya se est
acostumbrado,talescomocopiar,pegar,cortar,etc.,queaparecennormalmenteenelmen
deedicin.
Windows95supusounpasomuyimportanteenlafilosofadetrabajodelosPCs.Se
integra dentro de la familia de productos Windows de Microsoft, convirtindose en el
heredero de Windows 3.1, y compartiendo caractersticas de Windows para Trabajo en
Grupo, y Windows NT. Windows 95 es un entorno de trabajo de 32 bits con una interfaz
orientadaaobjetos,funcionesparatrabajoenredayudainteractiva,gestindemdemyfax.
Soport las ltimas tecnologas utilizadas hasta la fecha, como OLE 2.0, Plug and Play
(pincharyejecutar),llamadasaprocesosremotos,telefonamvil,etc.
En primer lugar, hay que sealar que Windows 95 es por s mismo un sistema
operativo, a diferencia de Windows 3.1 que necesita trabajar sobre el MSDOS. Esto quiere
decirqueelusuariocuandoarrancaelordenadornotieneprimeroquecargarelDOSy,luego,
ejecutarlaentoncesfamosaordenWINparacargarWindows.Ahoracuandoseenciendeel
ordenadorsearrancadirectamenteenWindows95.Porotraparte,elusuarioyanotieneque
instalarprimeroMSDOSyluegoWindows,sinosloinstalarWindows95directamente.
Ensegundolugar,esnecesariodestacarqueWindows95esunsistemaoperativode
32bits,optimizadoparalosordenadoresque,ensumayora,usanarquitecturade32bits.Las
ventajasdetrabajarconarquitecturade32bitsyenmodoprotegidosonbastantegrandes:
los programadores pueden usar un direccionamiento de memoria lineal y olvidarse de las
limitaciones que impone las direcciones segmentadas. Adems, se pueden ejecutar
controladoresdedispositivoenmodoprotegido,loquepermitevirtualizarlos;esdecir,que
un mismo dispositivo pueda ser compartido por varios programas a la vez, lo cual es un
276 PROGRAMACIN C++ Y COMUNICACIONES.
requisitoimprescindibleparaproporcionarverdaderamultitarea.Loscontroladoresvirtuales
soportantodoslosdispositivoshardwaredelordenador,incluyendodisco,teclado,monitor,
puertosparaleloyserie,etc.Tambinhaycontroladoresvirtualesparaelratn,SmartDrive,
sistema de ficheros VFAT, sistema de fichero CDROM, compresin de disco DriveSpace (y
DoubleSpace),tarjetasyprotocolosdered,dispositivosSCSI,etc.
PlugandPlay(ConectaryEjecutar)
UnadelascaractersticasmsatractivasdeWindows95esquesetratadelprimer
sistema operativo Plug and Play. El estndar o conjunto de normas Plug and Play pretende
crearunaestructuraquepermitagestionardeformainteligentelainstalacinyconfiguracin
denuevosdispositivos,sinrequerirlaintervencindelusuario.ConunsistemaPlugandPlay
el usuario puede aadir y quitar dispositivos o conectarse y desconectarse a una red o
estacin maestra sin necesidad de reinicializar el sistema y definir varios parmetros. El
sistema Plug and Play detecta automticamente la existencia de un nuevo dispositivo,
determina la configuracin ptima y permite que las aplicaciones se autoajusten
automticamenteteniendoencuentaloscambiosocurridos.Porejemplo,unaaplicacinque
muestradifuminadas,oinactivas,lasopcionesparaCDROMyquereconoceinmediatamente
lapresenciadeunaunidadCDROM,activandolaposibilidaddeseleccionarlasopcionespara
CDROM. De esta forma, los usuarios ya no necesitan conmutar puentes, activar
interruptores, seleccionar IRQs libres; ni siquiera tiene que cambiar los ficheros de
configuracindelsistemaoperativoparaadirlosnuevoscontroladores.
Paralograresteobjetivodeunainstalacininstantneayautomtica,unordenador
hadeposeertrescomponentes:unsistemaoperativoPlugandPlay,unaBIOSPlugandPlayy,
por supuesto, dispositivos compatibles Plug and Play. Estos tres componentes son
imprescindibles para evitar totalmente la intervencin del usuario durante el proceso de
instalacin, pero la existencia de dos o uno de ellos tambin simplifica la configuracin
hardware.
Enprimerlugar,losdispositivosPlugandPlaytienenquesercapacesdeidentificarse
a s mismos, es decir, informar al ordenador de qu tipo de dispositivo se trata y de los
requisitos que necesita. Por ejemplo, una tarjeta de sonido Plug and Play debe indicar al
ordenadorquesetratadeunatarjetadesonidoyquenecesitaseleccionarunaIRQ,uncanal
DMAyunadireccindememoriabase.Adems,debepermitirqueelordenadorconfigurede
formaautomticadichosrequisitos,locualimplicaquelosdispositivosPlugandPlaytienen
que poder modificarse a s mismos. Por ejemplo, en el caso de una impresora que exige la
presenciadeunpuertoparalelobidireccionalquepermitaenviardatosdesdelaimpresoraal
ordenador,ynoslodesdeelordenadoraalimpresora.
Ensegundolugar,tienequehaberunaBIOSPlugandPlayqueestpreparadapara
pedir y aceptar las caractersticas y los requisitos de los nuevos dispositivos. Esta BIOS
detectarlapresenciadeunnuevodispositivoy,envezdegenerarvariospitidosseguidosde
un escueto mensaje, pedir los valores por defecto para los requisitos del dispositivo y
seleccionarautomticamentelosadecuados.
Porltimo,esnecesariounsistemaoperativoPlugandPlay,talcomoWindows95,
quegestionetodosloscomponentescargandoloscontroladoresdedispositivoadecuadosy
reconfigurandoelsistemaautomticamentesinintervencindelusuario.
ElestndarPlugandPlaynoslopretendealcanzarunaconfiguracinautomticade
losdispositivoshardware,sino sercapazdereconocercambiosdinmicosdeconfiguracin.
Esta caracterstica es fundamental en la informtica mvil, puesto que los usuarios de
porttiles necesitan poder conectarse a redes locales sin tener que apagar el ordenador o
reconfigurarlo. Un sistema operativo Plug and Play, reconoce inmediatamente los nuevos
dispositivos instalados y los recursos que necesitan, cargando de forma automtica los
controladores de dispositivos adecuados. Las aplicaciones son informadas de los cambios
dinmicosparaquepuedanaprovecharlasnuevascaractersticas,obienimpidanelaccesoa
dispositivosnoexistentes.Supuestamenteyanoesprecisoapagaryreinicializarelordenador
cuandorealicencambiosenlaconfiguracinhardware,ynisiquierahandeintervenirenel
procesodeconfiguracin.
Interfazorientadaaobjetos
En la parte inferior de la pantalla existe una Barra de Tareas que cumple un papel
fundamental en la nueva interfaz adems de sustituir a la Lista de Tareas de Windows 3.1.
Cadavezqueseejecutaunaaplicacin,oseminimiza,apareceuniconoenlaBarradeTareas
querepresentadichaaplicacin.PuestoquelaBarradeTareassiempreestactiva,pulsando
el icono se accede inmediatamente a la aplicacin. Esto resuelve uno de los principales
problemas que tienen los usuarios de Windows 3.1: saber exactamente el nmero de
ventanas que tiene abiertas con aplicaciones ejecutndose y saber cmo acceder a una
ventanaquenoapareceenpantalla.
Lanuevainterfaz
El escritorio de Windows, puede utilizar como fondo una pgina Web, permite instalar los
componentes activos, pequeos trozos de cdigo HTML que muestran informacin
cambiante, como la cotizacin de bolsa o las ltimas noticias de un determinado tema, y
soporta protectores de pantalla de canales. Todas estas caractersticas son resultado de la
vistaWeb,pueselescritorionoesmsqueunacarpetadeldiscoduroy,portanto,poseela
capacidad de entender y mostrar cdigo HTML. Las barras de herramientas incluyen ahora
nuevas opciones. Ahora puede incluir en la barra de tareas iconos que ejecutan programas
automticamente de forma rpida y cmoda. Adems hay varios iconos predefinidos entre
losquedestacaunoqueminimizatodaslasventanasabiertas,dejandoelescritoriolimpio.
Perosindudalanovedadmsinteresanteeslacapacidaddetrabajarcondosmonitores.El
funcionamientoesmuysencillo:hayqueinstalarenelordenadordostarjetasdevdeo,que
puedenser2PCIO1PCIyAGP,yaquenosepuedenusartarjetasdevdeoISA,yconectar
los monitores correspondientes. A partir de ese momento Windows funciona con una
pantallavirtualqueeslasumadelosdosmonitores.Porejemplo,sitieneenunmonitor800
x600yenotro640x480,secreaunapantallavirtualde800x1080dondesepuedecolocar
libremente los objetos. Es decir, puede arrastrar un icono desde una pantalla a otra, pues
280 PROGRAMACIN C++ Y COMUNICACIONES.
paraWindowssetratadeunasolapantallavirtual.Tambinpuedehacerqueunprogramase
ejecuteenunodelosmonitores,usandoelotroparaotrastareas.
VentajasdelaFAT32
Herramientasdesistemayhardware
AdemsdelconvertidordeFAT32,Windows98incluyevariasherramientasdesistemacomo
elLiberadordeespacioendiscoduro,unprogramadecopiasdeseguridad,unprogramade
informacindelsistema.
Windows 98 est preparado para las ltimas tecnologas hardware y especificaciones que
estarnpresentesdeformamasivaenlosprximosaos.Sesoportanlasnuevastarjetasde
vdeo AGP (Accelerated Graphics Port, Puerto para Aceleracin de Grficos), que usan un
chipdevdeoqueaumentadrsticamentelavelocidaddeprocesamientogrficoalevitarel
busPCI,yutilizarunalneadirectaentreelsubsistemagrficoylamemoriadelordenador.
TambinsereconocenlosnuevosmdulosdecmarasdigitalesyloslectoresDVD.Windows
98estpreparadoparalosordenadoresconconectoresdetipoUSB(UniversalSerialBus,
Bus Serie Universal), que permite conectarhasta 127 dispositivos serie a unnico conector
delPC,comoescner,cmarasdigitales,ratones,mdems,impresoras,etc.Estaesunaforma
cmoda de eliminar la necesidad de cables y puertos serie adicionales. En este sentido,
Windows98soportaelestndarIEEE1394,cuyafuncinessimilaraldeUSB.Enelcampode
la administracin de energa, Windows 98 sigue el estndar ACPI (Advanced Configuration
and Power Interface, Configuracin Avanzada e Interfaz de Alimentacin), que permite al
ordenadoractivarodesactivarautomticamenteperifricoscomodiscosduros,impresoraso
tarjetasdered;porejemplo,desactivaelconsumo,yconelloelruidodeldiscoduro,cuando
se producen tiempos de inactividad, activndose automticamente al usar el teclado o el
ratn. Sealar tambin que Windows 98 soporta IrDA 3.0 (Infrared Data Association,
Asociacin de Datos por Infrarrojos), la ltima versin del estndar para comunicacin
inalmbricaatravsdeinfrarrojos.
FinalmenteWindowsScriptingHostpermiteejecutararchivosVisualBasicScriptoJavaScript,
tantodesdeelentornodeWindowscomodesdelalneadecomandosdelMSDOS.Deesta
forma,sepuedencrearenestoslenguajesverdaderosprogramasWindowsqueseejecutan
de forma sencilla y cmoda. A grandes rasgos, es una forma de retomar los habituales
archivosporlotesBAT,peroahoraconfuncionesdeWindowsyconmltiplesposibilidades.El
motor de Windows Scripting Host soporta los lenguajes VBScript y Jscript, pero compaas
independientespuedencrearcontrolesActiveXparaotroslenguajescomoPerl,TCLoREXX.
Comunicaciones
Elapartadodelascomunicacionesesunodelosmsimportantesentodosistemaoperativo
actual.LainclusindeExplorer4enWindows98suponedotarledeunvaloraadido
importante,puesaadeelnavegadorExplorer,unprogramadecorreo,ygruposdenoticias
OutlookExpress,uneditordepginasWebllamadoFrontPageExpress,yunaherramientade
telefonayvdeoconferenciadenomiandaNetMeeting.
MsnovedadesencomunicacionessonlanuevaversindeAccesotelefnicoaredes1.2,que
incluyesoporteparamultienlace;incluyndoseelprotocoloPPTPparacrearlasdenominadas
VPN(VirtualPrivateNetworks,RedesPrivadasVirtuales),quesonconexionessegurasauna
reddesdeInternet,actuandodelamismaformaquesiestuvieraconectadoalared.Unade
las novedades ms importantes de Windows 98, conocida como Web TV, se trata de la
posibilidadderecogerpginasWebatravsdelassealesdeTV,algosimilaralteletexto.
Estenuevosistemaoperativoincorporaavancesenlosdispositivosmultimedia,acordescon
las prestaciones de los computadores en que se instalan; es decir, Pentium II o III, con
elevadascapacidadesdealmacenamientoendiscoyenmemoriaRAM.Lafinalidadesofrecer
unentornoamigablealusuarioquelepermitarealizarfcilmentetareasdeedicindevdeo,
reproduccin y/o creacin de sonido, acceder a los diferentes servicios de Internet, etc.
EjemplodeestasnuevasprestacionessonlasaplicacionesqueMicrosoft,yotrosfabricantes,
suministran para Windows Millenium; como por ejemplo: Movie Maker, Windows Media
Player,..., para las aplicaciones de multimedia; y Microsoft Explorer 5.5, MSN Messenger y
NetMeetingparaaccesoalosdiversosserviciosqueofreceInternet.
Lasherramientasdeadministracinygestindelsistemaoperativo,alasquetieneaccesoel
usuario, son similares a las de Windows 98, aunque en algunos casos cambian de aspecto.
Pocas utilidades han sido aadidas a este sistema operativo, entre ellas destaca la de
restauracindelsistema,quepretenderecuperaralordenadorencasodequedarbloqueado;
eldesarrollodevariosasistentesparafacilitarlagestinyadministracindeaplicaciones;yel
control de instalacin de aplicaciones, que tendra la finalidad de evitar sobreescrituras no
deseadasenelprocesodeinstalacindenuevosprogramas.
Aumentodelavelocidadycapacidaddememoriadelosmicroprocesadores.
Soportedememoriavirtual.
Aumentodelasaplicacionescliente/servidorenredeslocales.
Todoestopermitiquelasaplicacionesfueranmscomplejaseinterrelacionadas,deforma
que un usuario puede estar utilizando varias aplicaciones simultneamente. Microsoft
desarrollWindowsNTconunaaparienciacaralausuariosimilaraWindows3.1,perobasado
en un concepto radicalmente distinto. Windows NT explota la potencia de sus
microprocesadores contemporneos de 32 bits y suministra una capacidad completa de
multitareaenunentornomonousuario.Adems,ofreceunagranpotenciaalpoderejecutar
aplicaciones escritas para otros sistemas operativos y cambiar de plataforma hardware sin
modificarelsistemaoperativonilasaplicaciones.
CaractersticasbsicasdeWindowsNT
Windows NT tiene una estructura modular, lo que le da una gran flexibilidad. Adems, se
puede ejecutar en una gran variedad de plataformas y soporta aplicaciones escritas para
otros sistemas operativos. Al igual que en otros sistemas operativos, en Windows NT se
distingueentreelsoftwareorientadoalasaplicaciones,queseejecutaenmodousuario;yel
software del sistema operativo, que se ejecuta en modo privilegiado como administrador.
Este ultimo tiene acceso a los datos del sistema y al hardware, mientras que el resto de
usuariostieneaccesoslimitados.
En la figura 9.4 se muestra la estructura de Windows NT. Para conseguir que NT tenga la
mismavisindelhardware,independientementedelsistemaenelqueseestejecutando,el
sistemaoperativosedivideencuatrocapas:
especfica;comoporejemplo,80486oPentiumdeIntel,PowerPCdeMotorola,
AlphaAXPdeDigital,etc.
Por encima de estas capas estn los subsistemas protegidos, que se encargan de la
comunicacin con el usuario final. Un
subsistemaprotegidoproporcionauna
interfaz de usuariogrfica, la lnea de
rdenesdelusuario.Otrafuncinque
tienen asignados es suministrar la
interfaz de programacin de
aplicacin (API, Application
Programming Interface). Esto
significaqueaplicacionescreadaspara
otros sistemas operativos pueden
ejecutarse sobre NT sin ninguna
modificacin, como es el caso de
OS/2,MSDOS,oWindows.
medianteotromensaje.Aspues,elservidoresunprogramaqueselimitaarealizaraquellas
funcionesquelesonsolicitadasdesdeelexterior.
OtroaspectoimportantedeWindowsNTessusoportedehebras (threats)dentrodelos
procesos. Las hebras incorporan algunas de las funcionalidades asociadas tradicionalmente
con los procesos. Una hebra es una unidad bsica de ejecucin, que se puede interrumpir
para que el procesador pase a otra hebra. Desde el punto de vista del planificador y del
distribuidor, este concepto es equivalente al de proceso en algunos sistemas operativos
anteriores. EnWindows NTun proceso esunconjuntode una,o ms,hebras juntocon los
recursosdelsistemaasociados,comosonlasparticionesdememoria,archivos,dispositivos,
etc.Estocorrespondealconceptodeprogramaenejecucin.
En NT no todas las entidades son objetos. De hecho, los objetos se emplean en los casos
dondelosdatosestnabiertosparaaccesoenmodousuarioocuandoelaccesoalosdatoses
compartidoorestringido.Entrelasentidadesrepresentadasporobjetosestnlosprocesos,
lashebras,losarchivos,lossemforos,losrelojesylasventanas.NTmanejatodoslostiposde
objetosdeunaformasimilar,medianteelgestordeobjetos,cuyaresponsabilidadescreary
eliminar los objetos segn la peticin de las aplicaciones y otorgar acceso a servicios de
objetosydatos.Unobjeto,yaseaunprocesoounahebra,puedereferenciaraotroobjeto
abriendoungestordelmismo.
286 PROGRAMACIN C++ Y COMUNICACIONES.
En NT los objetos pueden estar etiquetados, o no. Cuando un proceso crea un objeto no
etiquetado, el gestor de objetos devuelve un gestor al objeto, y la nica forma de
referenciarlo es mediante su gestor. Los objetos etiquetados tienen un nombre que puede
usarse por otro proceso para obtener el gestor del objeto. Los objetos etiquetados tienen
asociadalainformacindeseguridadenlaformadeuntestigodeacceso.Estainformacinse
puedeutilizarparalimitarelaccesoalobjeto.Porejemplo,unprocesopuedecrearunobjeto
semforoetiquetadodeformaqueslolosprocesosquelosconozcanlopuedanutilizar.El
testigodeaccesoasociadoconelsemforotendrunalistadetodoslosprocesosquepueden
accederal.
Gestindeprocesos
EntrelascaractersticasdelosprocesosdeNTsepuedenresaltar:
LosprocesosenNTsonimplementadoscomoobjetos
Unprocesoejecutablepuedetenerunaomshebras.
Tantolosobjetosdelosprocesoscomolosdalashebrasllevanincorporadaslas
capacidadesdesincronizacin.
Laconcurrenciaentrelosprocesosseconsigueporquehebrasdediferentesprocesos
se pueden ejecutar concurrentemente. Adems, si se dispone de varias CPUs, se pueden
asignar distintos procesos a hebras del mismo proceso, de forma que se ejecuten
concurrentemente. Las hebras del mismo proceso pueden intercambiar informacin entre
ellas a travs de la memoria compartida y tener acceso a los recursos compartidos del
proceso.
la familia de objetos de sincronizacin, que son entre otros: procesos, hebras, archivos,
sucesos semforos y relojes. Los tres primeros objetos tienen otros usos, pero tambin se
pueden utilizar para sincronizacin, el resto de los tipos de objetos se disean
especficamenteparasoportarlasincronizacin.
Gestindelamemoria
WindowsNTsediseparaimplementarloendiferentestiposdeprocesadores,yen
uno en los que ms se pens fue en el Intel 80486. Por ello, en Windows NT se adopta el
tamaodepginade4Kbytedel80486,comobasedesuesquemadememoriavirtual.Para
entender el esquema de memoria de Windows NT es conveniente estudiar los servicios de
memoriavirtualdel80486ydel80386.
Memorianisegmentada,nipaginada
Memoriapaginadaperonosegmentada
Memoriasegmentadaperonopaginada
Memoriasegmentadaypaginada.
Cuandoseempleasegmentacin,cadadireccinvirtual,olgica,secomponedeuncampo
dereferenciaalsegmentode16bits,dosdeellosdestinadosalosmecanismosdeproteccin
ycatorceparaespecificarelsegmento.Secuentaadems,conuncampodedesplazamiento
en el segmento de 32 bits; de esta forma, el espacio de memoria virtual que puede ver un
usuario es de 246=64 TB; mientras que el espacio de direcciones fsicas que se puede
direccionarcon32bitsesde4Gb.
Existen dos formas de proteccin asociadas con cada segmento: niveles de privilegio, y de
atributos de acceso. Son cuatro los niveles de privilegio, del 0 al 3, cuando se trata de un
segmentodedatoscorrespondealaclasificacindelmismoysiesunsegmentodeprograma
es su acreditacin. Un programa slo puede acceder a segmentos de datos para los que el
nivel de acreditacin es menor o igual que el de clasificacin. El uso de estos niveles de
privilegio depende del sistema operativo. Generalmente los niveles 0 y 1 corresponden al
sistemaoperativo,elnivel2aalgunossubsistemasyelnivel3alasaplicaciones.Losatributos
288 PROGRAMACIN C++ Y COMUNICACIONES.
deaccesodeunsegmentodedatosindicansielpermisodeaccesoesdelectura/escriturao
de slo lectura, y para un segmento de programa expresan si es de lectura/ejecucin o de
slolectura.
Ladireccinvirtualsetienequetransformarenunadireccinfsicamedianteunmecanismo
anlogo al explicado anteriormente. La segmentacin es una caracterstica opcional que se
puede desactivar. Cuando no se usa segmentacin los programas emplean direcciones
lineales, que corresponden a las direcciones en el espacio de memoria del proceso que
utilizan46bits,lacualhayqueconvertirenunadireccinrealde32bits.Elmecanismode
paginacinutilizadoparahacerestoconsisteenunaoperacindebsquedaenunatablade
dosniveles.Elprimernivelesundirectoriodepginasde1024entradas,conloquesedivide
elespaciodememoriade4Gbengruposde1024pginas,de4Mbdelongitudcadaunacon
su propia tabla de pginas. Cada tabla de pginas contiene 1024 entradas y cada entrada
correspondeaunapginade4Kb.Elgestordememoriapuedeusarundirectoriodepginas
para todos los procesos, un directorio de pginas para cada proceso o una combinacin de
ellos.Eldirectoriodepginasdelatareaactualestenmemoriaprincipal,perolastablasde
pginaspuedenestarenmemoriavirtual.
Windows2000esunsistemabasadoenlatecnologaNT,esdecir,quesiguiendocon
unanumeracincoherente,Windows2000enrealidaddeberahabersidoWindowsNT5.0.
Desde el punto de vista de la gestin de los equipos, las caractersticas de Windows 2000
hacen que una red basada en ste sistema sea ms fcil de administrar, facilitando la
instalacindeequiposclientesymejorandoelsoportedeperfilesflotantesyaccesoremoto.
RespectoaWindows98haheredadolafacilidaddeusoyelsoportededispositivosplugand
play;perointentandomantenerlarobustezyfiabilidaddeWindowsNT.
OtrodelosgrandesavancesquesehanproducidoenWindows2000seencuentra
enlaseguridadatodoslosniveles.Noslosehamejoradolaseguridaddecaraalaccesoal
sistemaoproteccindearchivos,sinoquetambinloscontroladoressonmssegurosqueen
Windows9x/NT.EstosedebeaqueMicrosoftcertifica los controladoresdelosfabricantes
que lo soliciten. Aunque, se pueden instalar controladores sin certificar, si se opta por los
certificados,setieneunamayorcertezadequetodovaafuncionarcorrectamente,evitando
engranmaneraelbloqueodeordenadordebidoaloscontroladores.
MejorasdeWindows2000.
EstafusindelasdosfamiliasdesistemasoperativosdeMicrosoftesunaviejaaspiracinde
estefabricante,quepretendefusionarlosenunsolo.Estanoesunatareafcilydehechouno
delosprincipalesrequisitosdediseoeshaciaqutipodeusuarioestdestinadoelsistema
operativo.EnelcasodeWindowsXP,elusuariodenominadodomsticosereldestinatario.
Este tipo de perfil limita significativamente el sistema operativo, ya que se supone que la
persona que va a trabajar y administrar la mquina, no debe tener problemas al instalar
aplicaciones y que todo debera instalarse casi automticamente, lo cual impide plantearse
cuestiones tan elementales como implantar una buena gestin de usuarios, el control de
procesos,etc.
AlgunasdelasprincipalesnovedadesaparecidasconWindowsXPhansidolaactivacindela
licenciadelsistemaoperativo,ylacertificacindelhardware.Laactivacindelicenciaesun
intento de lucha contra el pirateo del software, consiste en registrar cada una de las
instalaciones que realiza el usuario, de forma que combinando los nmeros series del
hardwaredelcomputadorydelalicenciadelsistemaoperativo,entoncesMicrosoftdevuelve
una clave quepermite lautilizacin correcta del ordenador,y encasocontrario se limitara
drsticamentesuuso.Evidentemente,surgennumerosascuestionesqueresolver,comoson
laactualizacindelhardwaredelequipo,elusodeequiposdiferentes,ylaaparicindecracks
queseinvalidanlosmecanismosdeactivacin.Elsegundopuntocitadodecertificacindel
hardware es un intento de estandarizacin de todos los dispositivos que puedan ser
instaladosalcomputador;aunquelafinalidadesinteresante,estetambinesunpuntocon
una gran polmica, ya que, los avances en velocidad y prestaciones del nuevo hardware
siempresonsuperioresalosavancesenlosestndares;yelotroaspectoeslagestindela
certificacin,yaquepodradarlugaraunmonopoliomuycuestionable.
El WindowsVistaeselprimersistemaoperativodeMicrosoftconcebidoparagarantizaruna
compatibilidad total con EFI (Extensible Firmware Interface), la tecnologa llamada a
reemplazar a las arcaicas BIOS que desde hace ms de dos dcadas han formado parte
indisoluble de los ordenadores personales, por lo tanto no emplear MBR (Master Boot
Record),sinoGPT(GUIDPartitionTable).
IntroducelasventanasdibujadascongrficosvectorialesusandoXAMLyDirectX.Paraello,
se utilizara una nueva API llamada Windows Presentation Foundation, cuyo nombre en
cdigoesAvalon,querequiereunatarjetagrficaconaceleracin3DcompatibleconDirectX.
AgregaunainterfazdelneadecomandodenominadaWindowsPowerShell,quefinalmente
seofrecicomounadescargaindependienteparaWindowsVistayWindowsXPSP2.
SeanunciunanuevaextensindebasededatosalsistemadearchivosllamadaWinFS.El
desarrollo de dicho sistema de ficheros ha sido abandonado por Microsoft, por lo tanto no
ser incluido en Windows Vista, por el momento, siendo compensado por un sistema de
bsquedabasadoenlaindexacin.
IntegradirectamenteenelsistemaunlectordenoticiasRSS(ReallySimpleSyndication,por
sussiglaseningls).
EnWindowsVistalautilidadderestauracindelsistemahasidoactualizadaeimplementada
comoherramientadeiniciodesesin,facilitandoaselrescatedelsistema.Ademsincluye
292 PROGRAMACIN C++ Y COMUNICACIONES.
Aadealfirewalldesistemalacapacidaddebloquearconexionesquesalendelsistemasin
previaautorizacin.
Se incluye Windows ReadyBoost, la cual es una tecnologa de cach de disco incluida por
primera vez en el sistema operativo Windows Vista. Su objetivo es hacer ms veloces a
aquellos computadores que se ejecutan con el mencionado sistema operativo mediante
pendrives,tarjetasSD,compactFlashosimilares.
YseincorporaalsistemalaherramientaEncriptadordediscoBitLocker,paralaproteccinde
datosextraviadosenlasversionesEnterpriseyUltimate.
Mejoranotablementeelsistemadecontroldecuentasdeusuario,queesunacaracterstica
del sistema que limita las operaciones de determinados tipos de usuarios en el equipo. A
diferencia de las anteriores versiones de Windows, los nuevos usuarios de Windows Vista
(concuentaestndar)notienenderechosdeadministradorpordefecto,comolainstalaciny
lamodificacinderegistrosdelsistema.Secaracterizaportenerunavariantedelabandera
deWindowsendoscolores,azulclaroyamarilloenlaesquinainferiorderechadecadabotn
o archivo de instalacin. Para realizar tareas administrativas, el monitor se oscurece, se
bloqueacualquierordendelratnoteclado;yapareceunaventanadeconfirmacin,lacual
solo autoriza aceptando la orden o tecleando una contrasea. Solo permite la activacin o
desactivacindeste.
IncluyeunSyncCenterparasincronizacindeWindowsVistaconPocketPCsinnecesidadde
instalarelActiveSync.
IncorporaunsistemadeproteccinllamadoWindowsSoftwareProtectionPlatform(WSPP)
queesmspotentequeelactualWindowsGenuineAdvantage(WGA).Cuandodetecteque
lacopiaesilegal,loprimeroqueharseravisaralusuario ysielusuarionolograobtener
unacopiaautnticaelprogramaempezarairdesactivandoopcionesdelsistema,comoson
el Aero o el Windows Defender hasta nicamente dejar activo lo ms bsico como es el
navegador.
Cargaaplicacionesun15%msrpidoqueWindowsXPgraciasalacaractersticaSuperFetch.
Sereduceenun50%lacantidaddevecesqueesnecesarioreiniciarelsistemadespusdelas
actualizaciones.
Labarradetareasfuerediseada,esmsancha,ylosbotonesdelasventanasyanotraen
texto, sino nicamente el icono de la aplicacin. Estos cambios se hacen para mejorar el
desempeoensistemasdepantallatctil.EstosiconossehanintegradoconlabarraInicio
rpido usada en versiones anteriores de Windows, y las ventanas abiertas se muestran
agrupadasenunnicoiconodeaplicacinconunborde,queindicaqueestnabiertas.Los
accesos directos sin abrir no tienen un borde. Tambin se coloc un botn para mostrar el
escritorioenelextremoderechodelabarradetareas,quepermiteverelescritorioalposar
elpunterodelratnporencima.
SeaadieronlasBibliotecas,quesoncarpetasvirtualesqueagreganelcontenidodevarias
carpetasylasmuestranenunasolavista.Porejemplo,lascarpetasagregadasenlabiblioteca
Vdeos son: Mis vdeos y Vdeos pblicos, aunque se pueden agregar ms,
manualmente. Sirven para clasificar los diferentes tipos de archivos (documentos, msica,
vdeos,imgenes).
Una caracterstica llamada Jump lists guarda una lista de los archivos abiertos
recientemente.Haciendoclicderechoacualquieraplicacindelabarradetareasapareceuna
jump list, donde se pueden hacer tareas sencillas segn la aplicacin. Por ejemplo, abrir
documentosrecientesdeOffice,abrirpestaasrecientesdeInternetExplorer,escogerlistas
de reproduccin en el reproductor, cambiar el estado en Windows Live Messenger,anclar
sitosodocumentos,etctera
Existen seis ediciones de Windows 7, construidas una sobre otra de manera incremental,
aunquesolamentesecentrarnencomercializardosdeellasparaelcomndelosusuarios:
las ediciones Home Premium y Professional. A estas dos, se suman las versiones Starter,
Home Basic, y Ultimate, adems de la versin Enterprise, que est destinada a grupos
empresarialesquecuentenconlicenciamientoOpenoSelectdeMicrosoft.
Starter:EslaversindeWindows7conmenosfuncionalidades. Poseeunaversin
incompletadelainterfazAeroquenoincluyelosefectosdetransparenciaGlass,Flip
3D o las vistas previas de las ventanas en la barra de inicio y adems no permite
cambiar el fondo de escritorio. Est dirigida a PC de hardware limitado como
netbooks, siendo licenciada nicamente para integradores y fabricantes OEM.
Incluye una serie de restricciones en opciones de personalizacin y de programas,
adems de ser la nica edicin de Windows 7 sin disponibilidad de versin para
hardwarede64bits.
Home Basic: Versin con ms funciones de conectividad y personalizacin, aunque
su interfaz seguir siendo incompleta como en la edicin Starter. Slo estar
disponible para integradores y fabricantes OEM en pases en vas de desarrollo y
mercadosemergentes.
HomePremium:Ademsdeloanterior,seincluyeWindowsMediaCenter,eltema
Aerocompletoysoporteparamltiplescdecsdeformatosdearchivosmultimedia.
Disponible en canales de venta minoristas como libreras, tiendas y almacenes de
cadena.
Professional:EquivalenteaVistaBusiness,peroahoraincluirtodaslasfuncionesde
la versin Home Premium ms Proteccin de datos con Copia de seguridad
avanzada,redadministradaconsoporteparadominios,impresinenredlocalizada
mediante Location Aware Printing y cifrado de archivos. Tambin disponible en
canalesdeventaalpblico.
Ultimate: Aadecaractersticas de seguridadyproteccin de datoscomo BitLocker
endiscosdurosexternoseinternos,Applocker,DirectAccess,BranchCache,soporte
a imgenes virtualizadasdediscos duros (en formatoVHD)y elpaquete de opcin
multilenguaje.
Enterprise: Esta edicin provee todas las caractersticas de Ultimate, con
caractersticas adicionales para asistir con organizaciones IT. nicamente se vende
porvolumenbajocontratoempresarialMicrosoftsoftwareAssurance.Tambinesla
nica que da derecho a la suscripcin del paquete de optimizacin de escritorio
MDOP.
EdicionesN:LasedicionesNestndisponiblesparaactualizacionesynuevascompras
de Windows 7 Home Premium, Professional y Ultimate. Las caractersticas son las
mismasquesusversionesequivalentes,peronoincluyenWindowsMediaPlayer.El
precio tambin es el mismo, ya que Windows Media Player puede descargarse
gratuitamentedesdelapginadeMicrosoft
MicrosoftlanzalaventalaversinfinaldeWindows8,el26deoctubrede2012,3aos
despusdellanzamientodesupredecesorWindows7.Selanzalpblicogeneralunaversin
dedesarrollo("ConsumerPreview")el29defebrerode2012.Microsoftfinalmenteanunci
unaversincasicompletadeWindows8,laReleasePreview,quefuelanzadael31demayo
de 2012 y es la ltima versin preliminar de Windows 8 antes de su lanzamiento oficial. El
desarrollodeWindows8concluyconelanunciodelaversinRTMel1deagostode2012
Windows8 ha recibido duras crticas desde su lanzamiento, lo que ha motivado ventas por
debajo de las expectativas para la empresa desarrolladora. Incluso el propio Paul Allen, co
fundador de Microsoft, ha dicho que este sistema operativo es extrao y confuso en un
primercontacto,perosehamostradoconfiadoenquelosusuariosaprendernaquererla
nuevaversin.
TheVergepensqueelnfasisdeWindows8enlatecnologafueunaspectoimportantede
laplataforma,yquelosdispositivosdeWindows8(especialmenteaquellosquecombinanlos
rasgosdelascomputadorasporttilesylastabletas)convertirainmediatamentealiPaden
algopasadodemodadebidoalascapacidadesdelmodelohbridodelsistemaoperativoyel
crecienteintersenelserviciodelanube.AlgunasdelasaplicacionesincluidasenWindows8
fueronconsideradasbsicasyconcarenciadeunafuncionalidadprecisa,perolasaplicaciones
deXboxfueronelogiadasporsupromocindeunaexperienciadeentretenimientoenmulti
plataforma. Otras mejoras y caractersticas (como el historial de archivos, los espacios de
almacenamiento y las actualizaciones para el administrador de tareas) fueron considerados
comocambiospositivos.36PeterBrightdeArsTechnicasintiquemientrassuscambiosde
interfazdeusuarioquizsloseclipse,lamejora,eladministradordearchivosactualizados,la
funcionalidaddeunnuevoalmacenamiento,lascaractersticasexpandidasdeseguridadyla
actualizacindelAdministradordeTareasdeWindows8fueronnotablesmejoraspositivas
paraelsistemaoperativo.BrightpensqueesadualidaddeWindows8hacialastabletasylos
PCtradicionalesfueronunaspectoextremadamenteambiciosodelaplataforma,perose
mantuvo crtico ante la decisin de Microsoft de emular el modelo de Apple como una
plataformadedistribucindondeimplementaunaWindowsStore.
LainterfazdeWindows8hasidoobjetodereaccionesmixtas.Brightindicqueelsistemade
Edge UI del puntero y desplazamiento no fueron muy obvios debido a la carencia de
instruccionesproporcionadasporelsistemaoperativoenlasfuncionesaccedidasatravsdel
interfazdelusuario,inclusoporelmanualdevdeoaadidoenellanzamientodelRTM(que
solamente instruye a los usuarios a apuntar las esquinas de la pantalla y el toque de sus
lados).Apesardeesteobstculoautodescrito,BrightaclaraquelainterfazdeWindows8
trabajmuybienenalgunoslugares,peroempezaserincoherentecuandosecambiaentre
los ambientes Metro y de escritorio, algunas veces a travs de medios inconsistentes.37
TomWarrendeTheVergeaclarquelanuevainterfazfueasombrosacomosorprendente,
contribuyendoaunaexperienciaincreblementepersonalunavezqueespersonalizadopor
el usuario. Al mismo tiempo, Warren vio que la interfaz tiene una empinada curva de
aprendizaje,yfuedifcildeusarconuntecladoyunratn.Sinembargo,sesealque,sibien
obligaalosusuariosautilizarlanuevainterfazconunautilidadmstctil,fueunmovimiento
arriesgado para Microsoft en su conjunto, que era necesario con el fin de impulsar el
desarrollodeaplicacionesparaelalmacndeWindows.
WindowsEmbeddedStandard,queesunsistemabasadoenWindowsNT;WindowsCEest
desarrolladoindependientemente.
OriginalmenteaparecibajoelnombredePocketPC,comounaramificacindedesarrollode
WindowsCEparaequiposmvilesconcapacidadeslimitadas.Enlaactualidad,lamayorade
lostelfonosconWindowsMobilevienenconunestiletedigital,queseutilizaparaintroducir
comandospulsandoenlapantalla.
SibienmuchospensamosqueWindowsMobilehabiasidodescontinuadotemporalmenteen
favordelnuevosistemaoperativoWindowsPhone,laampliagamadetelfonosindustriales
hahechoaMicrosoftoptarporunaterceralineadesistemasoperativosparamvilesqueha
llamado Windows Embedded Handheld 6.5, que vendra a ser la nueva linea de sistemas
operativosbasadosenWindowsMobile6.5
WindowsPhoneesunsistemaoperativomvildesarrolladoporMicrosoft,comosucesorde
laplataformaWindowsMobile.2Adiferenciadesupredecesor,estenfocadoenelmercado
de consumo generalista en lugar del mercado empresarial3 por lo que carece de muchas
funcionalidades que proporcionaba la versin anterior. Microsoft ha decidido no hacer
compatible Windows Phone con Windows Mobile por lo que las aplicaciones existentes no
funcionan en Windows Phone haciendo necesario desarrollar nuevas aplicaciones. Con
WindowsPhone,Microsoftofreceunanuevainterfazdeusuarioqueintegravariosservicios
en el sistema operativo. Microsoft planeaba un estricto control del hardware que
implementara el sistema operativo, para evitar la fragmentacin con la evolucin del
sistema,perohanreducidolosrequisitosdehardwaredetalformaquepuedequeesonosea
posible.4
UnixesunsistemaoperativomultiusuarioymultitareaescritoenellenguajeC.Ensu
diseosepusoespecialcuidadoenaislarlasrutinasdependientesdehardware,deformaque
fuera fcil transportarlo a diferentes plataformas. As se disponen de versiones para
prcticamente todo tipo de computadores, desde ordenadores personales, o estaciones de
trabajo,hastalossupercomputadores.
Historia
Unixtieneunalargaeinteresantehistoria.ElprimerdesarrollodeUnixsehizoenlos
laboratoriosBellenellenguajeensambladordelamquina.Prontosevioquenoeraprctico
tener que reescribir el sistema completamente para cada mquina, por lo que decidieron
hacerloenC,unlenguajedealtonivel.
Porotraparte,laUniversidaddeCaliforniaenBerkeleymodificsustancialmenteel
cdigooriginalygenerunaversindenominadaUnixBSD(BerkeleySoftwareDistributions,
Distribuciones de Software de la Universidad de Berkeley). Las numerosas mejoras de Unix
BSDhicieronquefabricantescomoSunMicrosystemsyDECbasaransusversionesdeUnixen
ladeBerkeley.
Mientrastanto,AT&Tcontinudesarrollandoymejorandosusistemayen1982sali
deloslaboratoriosBellunanuevaversincomercialdeUnixdenominadaUnixSystemIII,que
notuvogranxitoyfueseguidarpidamenteporUnixSystemV.Alfinaldeladcadadelos
80 se tenan dos versiones incompatibles de Unix, la Unix 4.3 BSD y la versin 3 de Unix
System V, con sus respectivos dialectos, puesto que cada vendedor aada a sus propias
caractersticas.Debidoaestepanoramahahabidodistintosintentosdecrearunestndar.El
primer intento serio se realiz bajo los auspicios del IEEE Standards Board, a travs del
proyecto POSIX (Portable Operating System Interface X, Interfaz X Portable del Sistema
Operativo).Esteestndar,conocidocomo1003.1eslainterseccindelUnixSystemVydel
302 PROGRAMACIN C++ Y COMUNICACIONES.
Unix4.3BSD.elresultadofuealgoparecidoalantepasadocomndelosdos,laversin7de
Unix.
Descripcin.
ElhardwareestrodeadoporelncleodeUnix,queeselautnticoSO,denominadoaspara
enfatizarsuaislamientodelasaplicacionesydelosusuarios.Sigueacontinuacinlacapade
libreras,quecontieneunprocedimientoparacadallamadaalsistema.EnelestndarPosixse
especificalainterfazdelalibreraynoeldelallamadaalsistema.Porencimadeestascapas,
todas las versiones de Unix proporcionan una serie de programas de utilidades, como el
procesador de rdenes (shell), los compiladores, los editores, los programas de
procesamientodetextoylasutilidadesparaelmanejodelosarchivos.Desdeelterminalel
usuariollamadirectamenteaestosprogramas.
Sepuedenconsiderartresinterfacesdistintas:
Lainterfazdellamadasalsistema.
Lainterfazdelibrera.
La interfaz del usuario, que est formada por los programas de utilidades
estndar.
Elautnticosistemaoperativoeselncleoqueinteractadirectamenteconelhardwareylas
rutinasprimitivas,quecorrespondenalbloquedecontroldelhardwareyenlapartesuperior
estlainterfazdellamadasalsistema,quepermitealsoftwaredealtonivelteneraccesoa
funcionesespecficasdelncleo.Elrestodelncleosepuededividirendospartesprincipales,
queestnasociadasalcontroldeprocesosyalagestindearchivosydelaentrada/salida.
Controlysincronizacindeprocesos.
En Unix todos los procesos, excepto dos procesos bsicos del sistema, se crean mediante
rdenesdelprogramadeusuario.Losdosprocesossonlosdearranqueeinicializacin.Los
nueveestadosenlosqueestarunprocesoson:
Ejecucinenmodousuario.
Ejecucinenmodoncleo.
304 PROGRAMACIN C++ Y COMUNICACIONES.
Preparadoparaejecucinenmemoriaprincipal,tanprontocomoloplanifiqueel
ncleo.
Esperaenmemoriaprincipal.Elprocesoestenlamemoriaprincipalesperando
queocurraunsuceso.
Zombi. El proceso ejecuta la llamada exit() (fin del programa), pero todava no
puede finalizar por lo que queda en estado zombi. Normalmente, un proceso
pasa a estado de zombi cuando est a la espera de que finalice alguno de sus
hijos.
Comunicacinentreprocesos
EnUnixsetienendistintosalgoritmosparalacomunicacinysincronizacinentreprocesos.
Entreestos,losmsimportantesson:
Tuberas(pipes).
Seales.
Mensajes.
Memoriacompartida.
Semforos.
Lastuberaspermitentransferirdatosentreprocesosysincronizarlaejecucindelosmismos.
Usanunmodelodeproductorconsumidor,yhayunacolaFIFOdondeunprocesoescribeyel
otrolee.
Las tuberas y las seales constituyen una forma limitada de comunicacin. Los otros
mecanismosestndardecomunicacinson:
3. Lossemforos,quepuedensincronizarlaejecucindelosprocesos.
Losmensajessoncadenasdedatosconunformatoestablecido.Elprocesoqueenvaun
mensajeespecificaeltipodelmismoconcadaunodelosqueenva.Elreceptorpuede
usarestedatocomouncriteriodeseleccin,deformaquepuedeatenderalosmensajes
segnelordendellegadaenunacolaoporeltipo.Cuandounprocesointentaenviarun
mensajeaunacolaqueestllena,elprocesoquedasuspendido,lomismoocurresi
intentaleerdeunacolavaca.
Lossemforossincronizanygestionanelusoderecursos.Secreanenconjuntos,unconjunto
consta de uno o ms semforos. Esta generalizacin de los semforos da una considerable
flexibilidadenelfuncionamientodelasincronizacinycoordinacindelosprocesos.
Gestindelamemoria
306 PROGRAMACIN C++ Y COMUNICACIONES.
EnlasprimerasversionesdeUnixnosetenanesquemasdememoriavirtual,nicamentese
utilizaban particiones variables de memoria. En la actualidad, muchas de las
implementaciones hacen uso de memorias virtual paginada, utilizndose esquemas de
intercambioypaginacin.
Aunqueelesquemadegestindelamemoriavaradeunsistemaaotro,enUnixSystemVse
emplean unas estructuras de datos, que con pequeos cambios, son independientes de la
mquina.Estasestructurasson:latabladepginas,eldescriptordebloquesdeldisco,latabla
de datos de pgina y la tabla del intercambiador. Se tiene una tabla de pginas para cada
proceso, con una entrada para cada una de las pginas de memoria virtual del proceso.
Asociada con cada pgina de un proceso hay una entrada en el descriptor de bloques del
discoquedescribelacopiaeneldiscodelapginavirtual.Enlatabladedatosdelmarcode
pgina se describe cada uno de los marcos de la memoria real. El ndice de la tabla es el
nmero del marco. Hay varios punteros utilizados para crear listas dentro de la tabla. Los
marcosdisponiblesseenlazanjuntosenunalistademarcoslibres.
Por ltimo, la tabla de intercambio tiene una entrada por cada pgina en el dispositivo y
existeunaporcadadispositivodeintercambio.Estatablatienedosentradas:elcontrolador
dereferencia,queeselnmerodepuntosdeentradasdelatabladepginasaunapginaen
eldispositivodeintercambio,yelidentificadordelapginaenlaunidaddealmacenamiento.
Sistemadearchivos
EnUnixsedistinguencuatrotiposdearchivos:
Ordinarios. Son los archivos que contiene la informacin del usuario, los
programasdeaplicacinodeutilizacindelsistema.
Especiales.Estoscorrespondenalosperifricos:impresoras,discos,etc.
Etiquetados.Sonlostubosetiquetadosdiscutidosanteriormente.
TodoslostiposdearchivosdeUnixsegestionanporelsistemaoperativomediantelos
nodosi.Estoscorrespondenaunatablaquecontienelosatributosylasdireccionesdelos
bloquesdelarchivo.Losarchivosseubicandinmicamente,segnesnecesario,sinusar
unapreubicacin,deestaforma,losbloquesdeunarchivoeneldisconoson
necesariamentecontiguos.
Subsistemadeentrada/salida
ParaelsistemaoperativoUnixtodoslosperifricosestnasociadosaunarchivoespecial,que
segestionaporelsistemadearchivos,pudindoseleeryescribircomootroarchivoms.Se
consideran dos tipos de perifricos: de bloque y de carcter. Los perifricos de bloque son
perifricos dealmacenamiento deacceso arbitrario (porejemplo los discos). Losperifricos
orientados a caracteres incluyen a los otros tipos, por ejemplo las impresoras o los
terminales.
LaE/Ssepuederealizarutilizandounbuffer,comounazonadealmacenamientointermedio
de los datos procedentes o con destino a los perifricos. Hay dos mecanismos de buffer:
sistema de cach y colas de caracteres. El cach de buffer es esencialmente una cach de
disco.LatransferenciadedatosentrelacachdelbufferyelespaciodeE/Sdelprocesodel
usuarioserealizamedianteDMA,yaqueambosestnlocalizadosenlamemoriaprincipal.El
otro mecanismo de buffer, las colas de caracteres, resulta apropiado para los perifricos
orientados a caracteres. El dispositivo de E/S escribe una cola de caracteres que son ledos
porelprocesoo,inversamente,elprocesolosescribeyelperifricoloslee.Enamboscasos
seutilizaunmodelodeproductorconsumidor.
LaE/Ssinbufferessimplementeunaoperacindeaccesodirectoamemoria(DMA,Direct
MemoryAccess),entreelperifricoyelespaciodememoriadelproceso.Esteeselmtodo
msrpidopararealizarunaentrada/salida,sinembargo,unprocesoqueestrealizandouna
transferenciadeentrada/salidasinbufferestbloqueadoenlamemoriaprincipalynopuede
intercambiarse.
308 PROGRAMACIN C++ Y COMUNICACIONES.
LinuxfueelproyectooriginaldeunestudiantedeinformticallamadoLinusTorvalds
que entonces tena veintitrs aos. Linux empez siendo un pasatiempo para Linus, que
esperaba crear una versin ms slida de UNIX para usuarios de Minix. Tal y como
apuntbamos antes, Minix es un programa desarrollado por el profesor de informtica
AndrewTannebaum.
PropiedaddeLinux
Linus Torvalds conserva los derechos de autor del kernel bsico de Linux. Red Hat,
Inc,poseelosderechosdeladistribucinRedHatyPaulVolkerding,queseacogenalaGPL
(GeneralPublicLicense,LicenciaPblicaGerenal)deGNU.Deecho,Linuxymuchosdelos
quehancontribuidoaldesarrollodeLinux,hanprotegidosutrabajoconlaGPLdeGNU.
Enocasiones,estalicenciasedenominaGNUCopyleft,quenoesmsqueunjuego
de palabras con el trmino ingls Copyright. Esta licencia cubre todos los programas
producidos por GNU y por la FSF (Free Software Foundation, Fundacin de Software de
Libredistribucin).Estalicenciapermitealosdesarrollarescrearprogramasparaelpblicoen
general.LapremisafundamentaldeGNUesladepermitiratodoslosusuariosaccesolibrea
losprogramasconlaposibilidaddemodificarlos,siaslodesean.Lanicacondicinimpuesta
es que no puede limitarse el cdigo modificado; es decir, que el resto de usuarios tiene
derechotambinautilizarelnuevocdigo.
El GNU Copyleft, o GPL, permite a los creadores de programas conservar sus derechos de
autor,peropermitiendoalrestodeusuarioslaposibilidaddecopiarlos,modificarlosyhasta
de venderlos. Sin embargo, al hacerlo, no pueden limitar ningn derecho similar a los que
comprenelprograma.Sisevendeelprogramatalycomoest,ounamodificacindelmismo,
el usuario debe facilitar adems el cdigo fuente. Por ello, cualquier versin de Linux
incorporasiempreelcdigofuentecompleto.
LadistribucindeLinuxcorreacargodedistintascompaas,cadaunadeellascon
su propio paquete de programas, aunque todas faciliten un ncleo de archivos que
conformanunaversindeLinux.Lasmsdifundidasson:DebianLinux,RedHat,Slackware,
MandrakeyUbuntu.
CaractersticasdeLinux
Alguna de las ventajas que ofrece la multitarea preferente, adems de reducir los tiempos
muertos, es decir, aquellos momentos en los que no puede ejecutar ninguna aplicacin
porquetodavanosehacompletadounatareaanterior,poseeunagranflexibilidad,quele
permiteabrirnuevasventanassintenerquecerrarotrasconlasqueesttrabajando.
LacapacidaddeLinuxparaasignareltiempodemicroprocesadorsimultneamenteavarias
aplicaciones,lgicamentepermitiofreceraccesoavariosusuariosalavez,ejecutandocada
uno de ellos una o varias aplicaciones. La gran ventaja de Linux y de sus caractersticas de
multitareaymultiusuarioesquemsdeunusuariopuedetrabajarconlamismaversindela
aplicacin al mismo tiempo y desde el mismo terminal o desde terminales distintos. Sin
embargo,estacapacidaddeLinuxnodebeconfundirseconelhechodequevariosusuarios
puedanactualizarelmismoarchivosimultneamente,algoquepodrallevaralaconfusiny
alcaostotal,yporelloresultaindeseable.
Shellprogramables
310 PROGRAMACIN C++ Y COMUNICACIONES.
Aunque muchas versiones UNIX y Linux incluyen ms de un tipo de shell, todos ellos
funcionanbsicamentedelmismomodo.Unshellrealizalatareademediarentreelusuarioy
el ncleo del sistema operativo Linux. La diferencia esencial entre los tres shell disponibles
radicaenlasintaxisdelalneaderdenes.Aunquenosuponeunalimitacinestrictamente
hablando,elusodelasrdenesdelshellColasintaxisdelosshellsBourneobashpueden
traerleproblemas.
Algunosusuariosvaninclusomsall,diseandoprogramasqueenlazanprocesosy
aplicaciones para reducir su trabajo a veces hasta una nica sesin de entrada de datos,
consiguiendo as que el sistema actualice de una sola vez los numerosos paquetes de
programas.
IndependenciadedispositivosbajoLinux
UNIX soluciona los problemas que supone aadir otros perifricos, contemplando
cada uno de ellos como un archivo aparte. Cuando se necesitan nuevos dispositivos, el
administrador del sistema aade al kernel el enlace necesario. Este enlace, tambin
denominadocontroladordedispositivo,seocupadequeelkernelyeldispositivosefusionen
delmismomodocadavezquesesolicitaelserviciodeldispositivo.
VentajasydesventajasdelusodeLinux
Linux integra adems una implementacin completa del protocolo de red TCP/IP.
Linux permite conectarse a Internet y acceder a toda la informacin que incluye. Linux
tambindisponedeunsistemacompletodecorreoelectrnicoconelquesepuedeenviary
recibirmensajesatravsdeInternet,yotrasredesdeordenadores.
elementosGUIhabitualesqueincluyenotrasplataformasGUIcomerciales,comoWindowsy
OS/2.
OtradesventajadeLinuxesquesuinstalacinpuederesultardifcilynofuncionaen
todas las plataformas de hardware. A diferencia de los programas comerciales, donde un
mismo equipo de desarrolladores pasa meses construyendo y probando un programa en
distintascondicionesycondiferenteshardware,losdesarrolladoresdeLinuxseencuentran
repartidos por todo el mundo. No existe un programa formal que garantice la calidad de
Linux,sinoquelosdistintosdesarrolladoreslanzansusversionescuandoquiere.Adems,el
hardware admitido por Linux depende del utilizado por el desarrollador en el momento de
escribir esa parte del cdigo. Por tanto, Linux no funciona con todo el hardware disponible
actualmenteparaPC.
Varios sistemas operativos distintos pueden coexistir sobre el mismo ordenador, en slido
aislamiento el uno del otro, por ejemplo para probar un sistema operativo nuevo sin
necesidaddeinstalarlodirectamente.
La mquina virtual puede proporcionar una arquitectura de instrucciones que sea algo
distintadeladelaverdaderamquina.Esdecir,podemossimularhardware.
Ejemplos:VmWare,VirtualBox,MicrosoftVirtualServer,etc.
Definicin y tipos.
Unareddecomputadoresesunaagrupacindedosomscomputadoresquesecomunican
entres.Segnladimensindelaredsesuelendividirendosgrupos:
Redesderealocal(LAN,LocalAreaNetwork).Conectancomputadorescercanos
unosdelasotros.Enalgunoscasos,"local"significadentrodelamismahabitacino
edificio; en otros casos, se refiere a computadoresubicados a varios kilmetros de
distancia.
Redes de rea extendida o redes de gran alcance (WAN, Wide Area Network).
Constan de computadores que se encuentran en diferentes ciudades o incluso
pases. Son redes de larga distancia, debido al gran trayecto que debe recorrer la
informacinqueintercambian.
Compartir recursos. Todos los programas, datos y equipos, estn disponibles para
cualquier ordenador de la red que lo solicite, sin importar la localizacin fsica del
recursoydelusuario.
Mejora de la fiabilidad. Proporcionan una alta fiabilidad, al contar con fuentes
alternativasdesuministro.LapresenciademltiplesCPU,significaquesiunadeellas
deja de funcionar, las otras son capaces de su trabajo, aunque se tenga un
rendimientoglobalmenor.
Ahorro econmico. Los ordenadores pequeos tienen una mejor relacin
coste/rendimiento,comparadaconlaofrecidaporlasmquinasgrandes.Estasson,a
grandesrasgos,diezvecesmsrpidasqueelmsrpidodelosmicroprocesadores,
perosucostoesmilesdevecesmayor.
Mediodecomunicacin.Unareddeordenadorespuedeproporcionarunpoderoso
mediodecomunicacinentrepersonasqueseencuentranmuyalejadasentres.Ala
largaelusoderedes,comounmedioparaenriquecerlacomunicacinentreseres
humanos, puede ser ms importante que los mismos objetivos tcnicos, como por
ejemplo,lamejoradelafiabilidad.
Accesoaprogramasremotos.Unaempresaquehaproducidounmodeloquesimula
la economa mundial puede permitir que sus clientes se conecten usando la red y
ejecuten el programa para ver cmo pueden afectar a sus negocios las diferentes
proyeccionesdeinflacin,detasasdeintersydefluctuacionesdetiposdecambio.
Acceso a bases de datos remotos. Hoy en da, ya es muy fcil ver, por ejemplo, a
cualquierpersonahacerdesdesucasareservasdeavin,autobs,barcoyhoteles,
restaurantes, teatros, etc., para cualquier parte del mundo y obteniendo la
confirmacindeformainstantnea.Enestacategoratambincaenlasoperaciones
bancariasquesellevanacabodesdeeldomicilioparticular,ascomolasnoticiasdel
peridicorecibidasdeformaautomtica.
Medios alternativos de comunicacin. La utilizacin del correo electrnico, que
permite mandar y recibir mensajes de cualquier parte del mundo, muestra el gran
potencial de las redes en su empleo como medio de comunicacin. El correo
electrnicoescapazdetransmitirlavozdigitalizada,fotografaseimgenesmviles
devdeo.
316 PROGRAMACIN C++ Y COMUNICACIONES.
Arquitecturas de redes
Lamayoradelasredesseorganizanenunaseriedecapasoniveles,conobjetodereducirla
complejidaddesudiseo.Cadaunadeellasseconstruyesobresupredecesora.Elnmerode
capas, el nombre, el contenido, y la funcin de cada una varan de una red a otra. Sin
embargo,encualquierred,elpropsitodecadacapaesofrecerciertosserviciosalascapas
superiores,liberndolasdelconocimientodetalladosobrecmoserealizandichosservicios.
Lacapanenunamquinaconversaconlacapandeotramquina.Lasreglasyconvenciones
utilizadasenestaconversacinseconocencomoprotocolodelacapan.Alasentidadesque
formanlascapascorrespondientesenmquinasdiferentesselesdenominaprocesopares;es
decir de igual a igual. En otras palabras, son los procesos pares los que se comunican
medianteelusodelprotocolo.
Enrealidad,noexisteunatransferenciadirectadedatosdesdelacapandeunamquinaala
capa n de otra, sino ms bien, cada capa pasa la informacin de datos y control a la capa
inmediatamente inferior; y as sucesivamente, hasta que se alcanza la capa localizada en la
partemsbajadelaestructura.Debajodela1estelmediofsico,atravsdelcualserealiza
lacomunicacinreal.
Entre cada par de capas adyacentes existe una interfaz, la cual define los servicios y
operaciones primitivas que la capa inferior ofrece a la superior. Al conjunto de capas y
protocolos se le denomina arquitectura de la red. Las especificaciones de sta debern
contener la informacin suficiente que le permita al diseador escribir un programa o
construirelhardwarecorrespondienteacadacapa,yquesigaenformacorrectaelprotocolo
apropiado. Tanto los detalles de realizacin, como las especificaciones de las interfaces, no
forman parte de la arquitectura, porque se encuentran escondidas en el interior de la
mquinaynosonvisiblesdesdeelexterior.Msan,noesnecesarioquelasinterfacesde
todaslasmquinasenunaredseaniguales,supuestoquecadaunadelasmquinasutilice
correctamentetodoslosprotocolos.
La abstraccin del proceso par es importante para el diseo de redes, sin esta tcnica de
abstraccin sera difcil, dividir el diseo de una red completa; es decir, sera un problema
intratable si no se divide en varios ms pequeos y manejables, el diseo de capas
individuales. En la figura 10.2 se muestra un esquema del significado de los trminos capa,
protocoloeinterfaz.
Elmodeloquesevaatrataracontinuacinestbasadoenunapropuestadesarrolladaporla
Organizacin Internacional de Normas (ISO). Este modelo supuso un primer paso hacia la
normalizacin internacional de varios protocolos, [Stallings 00] y [Tanenbaum 97]. A este
modelo se le conoce como Modelo de Referencia Interconexin de sistemas abiertos, ms
conocido como modelo OSI de ISO, (OSI, Open System Interconnection). Este modelo de
referenciaserefierealaconexindesistemasheterogneos,esdecir,asistemasdispuestosa
establecercomunicacinconotrosdistintos.
El modelo OSI consta de 7 capas. Los principios aplicados para el establecimiento de siete
capasfueronlossiguientes:
2. Cada capa deber efectuar una funcin bien definida, que le proporcione entidad
propia.
3. Lafuncinquerealizarcadacapadeberseleccionarseconlaintencindedefinir
protocolosnormalizadosinternacionalmente.
318 PROGRAMACIN C++ Y COMUNICACIONES.
4. Loslmitesdelascapasdebernseleccionarsetomandoencuentalaminimizacin
delflujodeinformacinatravsdelasinterfaces.
Obsrvese que le modelo OSI, por s mismo, no es una arquitectura de red, dado que no
especifica, en forma exacta, los servicios y protocolos que se utilizarn en cada una de las
capas.Sloindicaloquecadacapadeberhacer.
Capa fsica.
La capa fsica se ocupa de la transmisin de bits a lo largo del canal de comunicacin. Los
problemas de diseo a considerar aqu son los aspectos mecnico, elctrico, de
procedimiento de interfaz y el medio de transmisin fsica, que se encuentra bajo la capa
fsica.
Capa de enlace.
La tarea primordial de la capa de enlace consiste en, a partir de un medio de transmisin
comnycorriente,transformarloenunalneasinerroresdetransmisinparalacapadered.
Estatarearequierequeelemisortroceelaentradadedatosentramasdedatos,tpicamente
construidas por algunos cientos de octetos. Las tramas as formadas son transmitidas de
forma secuencial, y requieren de un asentimiento del receptor que confirme su correcta
recepcin.
Capa de red.
La capa de red se ocupa del control de la operacin de la subred. Un punto de suma
importanciaensudiseo,esladeterminacinsobrecmoencaminarlospaquetesdeorigen
a destino. Si en un momento dado hay demasiados paquetes presentes en la subred, ellos
mismos se obstruirn mutuamente y darn lugar a un cuello de botella. El control de tal
congestin depender de la capa de red. Adems, es responsabilidad de la capa de red
resolverproblemasdeinterconexinderedesheterogneas.
Capa de transporte.
La funcin principal de la capa de transporte consiste en aceptar los datos de la capa de
sesin,dividirlos,siemprequeseanecesarioenunidadesmspequeas,pasarlosalacapade
red, y asegurar que todos ellos lleguen correctamente al otro extremo. Adems, todo este
trabajo se debe hacer de manera eficiente, de tal forma que asle la capa de sesin de los
cambiosinevitablesalosqueestsujetalatecnologadelhardware.
Capa de sesin.
La capa de sesin permite que los usuarios de diferentes mquinas puedan establecer
sesiones entre ellos. A travs de una sesin se puede llevar a cabo un transporte de datos
ordinario, tal y como lo hace la capa de transporte, pero mejorando los servicios que sta
proporcionayqueseutilizanenalgunasaplicaciones.
Uno de los servicios de la capa de sesin consiste en gestionar el control de dilogo. Las
sesionespermitenqueeltrficovayaenambasdireccionesalmismotiempo,obien,enuna
sola direccin en un instante dado. Otros servicios relacionados con esta capa son la
administracindeltestigoylasincronizacin.
Capa de presentacin.
A diferencia de las capas inferiores, que nicamente estn interesadas en el movimiento
fiabledebitsdeunlugaraotro,lacapadepresentacinseocupadelosaspectosdesintaxisy
semnticadelainformacinquesetransmite.
Lacapadepresentacinesttambinrelacionadaconotrosaspectosderepresentacindela
informacin. Por ejemplo, la compresin de datos se puede utilizar aqu para reducir el
320 PROGRAMACIN C++ Y COMUNICACIONES.
nmerodebitsquetienenquetransmitirse,yelconceptodecriptografasenecesitautilizara
menudoporrazonesdeprivacidadydeautentificacin.
Capa de aplicacin.
Lacapadeaplicacincontieneunavariedaddeprotocolosquesenecesitanfrecuentemente.
Porejemplo,haycentenaresdetiposdeterminalesincompatiblesenelmundo.Unaformade
resolveresteproblemaconsisteendefinirunterminalvirtualderedabstracto.
Lacapadepresentacintransformaesteelementodediferentesformas,conlaposibilidadde
introducir una cabecera en la parte frontal, dando el resultado a la capa de sesin. Es
importanteobservarquelacapadepresentacindesconocequpartedelosdatosqueledio
lacapadeaplicacin,correspondeaAH,yculessonlosquecorrespondenalosverdaderos
datosdelusuario.
Esteprocesosesiguerepitiendohastaquelosdatosalcanzanlacapafsica,lugarendonde
efectivamentesetransmitendatosalamquinareceptora.Laideafundamental,alolargode
esteproceso,esquesibienlatransmisinefectivadedatosesvertical,comosemuestraen
lafigura3.3,cadaunadelascapasestprogramadacomosifueraunatransmisinhorizontal.
LasentidadesdelacapaNdesarrollanunservicioqueutilizalacapa(N+1),enestecasoala
capaNseledenominaproveedordelservicioyalacapa(N+1)usuariodelservicio.LacapaN
puedeutilizarserviciosdelacapa(N1)conobjetodeproporcionarsuservicio.
Para que se lleve a cabo el intercambio de informacin entre dos capas, deber existir un
acuerdosobreunconjuntodereglasacercadelainterfaz.Enunainterfaztpica,laentidadde
lacapa(N+1)pasaunaUnidaddeDatosdelaInterfaz(IDU,InterfaceDataUnit)alaentidad
delacapaN,atravsdelcorrespondienteSAP.
El IDU consiste en una Unidad de Datos del Servicio (SDU, Service Data Unit) y de alguna
informacindecontrol.LaSDUeslainformacinquesepasa,atravsdelared,alaentidad
paryposteriormente,alacapa(N+1).Lainformacindecontrolesnecesariaporqueayudaa
quelascapasinferioresrealicensutrabajo;porejemplo,elnmerodebytesenelSDU,que
noformapartedelosdatos.
ParahacerlatransferenciadeunaSDU,podrsernecesariosufragmentacinporpartedela
entidaddelacapaNenvariaspartes,detalformaqueacadaunadeellasseleasigneuna
cabecerayseenvecomounadistintaUnidaddeDatosdelProtocolo(PDU,ProtocolData
Unit).LasentidadesparesutilizanlascabecerasdelaPDUparallevaracabosuprotocolode
igualaigual.PormediodeellosseidentificaculessonlasPDUquecontienendatosycules
lasquellevaninformacindecontrol.
Con frecuencia a las PDU de transporte, sesin y aplicacin se les conoce como Unidad de
DatosdelProtocolodeTransporte(TPDU,TransportProtocolDataUnit),UnidaddeDatos
delProtocolodeSesin(SPDU,ServiceProtocolDataUnit)yUnidaddeDatosdelProtocolo
deAplicacin(APDU,ApplicationProtocolDataUnit),respectivamente.
Las capas pueden ofrecer dos tipos diferentes de servicios a las capas que se encuentran
sobreellas;unoorientadoaconexinyotrosinconexin.
Losconceptosdeservicioyprotocolotienenunsignificadodiferente,ysoncomplementarios
entres,ladefinicindeservicioyprotocolosegnlaterminologaOSIeslasiguiente:
Unprotocolo,adiferenciadelconceptodeservicio,esunconjuntodereglasquegobiernanel
formatoyelsignificadodelastramas,paquetesomensajesquesonintercambiadosporlas
entidadescorresponsalesdentrodeunacapa.Lasentidadesutilizanprotocolospararealizar
324 PROGRAMACIN C++ Y COMUNICACIONES.
susdefinicionesdeservicio,teniendolibertadparacambiardeprotocolo,peroasegurndose
denomodificarelserviciovisiblealosusuarios.
Normalizacin de redes
Enlosprimerostiemposenqueaparecielconceptoderedes,cadacompaafabricantede
ordenadorestenasuspropiosprotocolos;porejemplo,IBMtenamsdeunadocena.Esto
daba como resultado que aquellos usuarios que adquiran ordenadores de diferentes
compaas,nopodanconectarlosyestablecerunasolaredconellos.Elcaosgeneradopor
esta incompatibilidad dio lugar a la exigencia de los usuarios para que se estableciera una
normalizacinalrespecto.
Lasnormassedividenendoscategorasquepuedendefinirsecomo:defactoydejure.Las
normas De Facto (derivado del latn, que significa "del hecho"), son aquellas que se han
establecidosinningnplanteamientoformal.LasnormasIBMPCysussucesorassonnormas
de facto para ordenadores pequeos de oficina, porque docenas de fabricantes decidieron
copiar fielmente las mquinas que IBM sac al mercado. En contraste, las normas De Jure
(derivadodellatn,quesignifica"porley"),sonnormasformales,legales,adoptadasporun
organismo que se encarga de su normalizacin. Las autoridades internacionales encargadas
delanormalizacinsedividen,porlogeneral,endosclases:laestablecidaporconvenioentre
gobiernosnacionales,ylaestablecidasinuntratadoentreorganizacionesvoluntariamente.
LaISOconstadeaproximadamente200comitstcnicos(TC),cuyoordendenumeracinse
basa en el momento de su creacin, ocupndose cada uno de ellos de un tema especfico.
CadaunodelosTCtienesubcomits(SC),loscualesasuvezsedividenengruposdetrabajo
(WG).
institucin,ademsdepublicarnumerosasrevistasyprogramarunnmeromuyimportante
deconferenciasanuales,haestablecidoungrupodedicadoaldesarrollodenormasenelrea
delaingenieraelctricaycomputacin.
Ejemplos de redes
Actualmenteseencuentrafuncionandounnmeromuygrandederedesentodoelmundo.
Algunas de ellas son redes pblicas operadas por proveedores de servicios portadores
comunesoPTT,otrasestndedicadasalainvestigacin,tambinhayredesencooperativa
operadasporlosmismosusuariosyredesdetipocomercialocorporativo.Lasredes,porlo
general,secaracterizanporlospuntoscitadosacontinuacin:
Losserviciosofrecidos,quepuedenvariardesdeunacomunicacinarbitrariadeproceso
a proceso, hasta el desarrollo de un sistema de correo electrnico, transferencia de
archivosoaccesoremoto.
Porltimo,lascomunidadesdeusuarios,quepuedenvariardesdeunasolacorporacin,
hasta aquella que incluye todos los ordenadores cientficos que se encuentran en el
mundoindustrializado.
Redes pblicas: Las empresas privadas, y los gobiernos de varios pases han
comenzado a ofrecer servicios de redes a cualquier organizacin que desee
subscribirse a ellas. La subred es propiedad de la compaa operadora de redes y
proporcionaunserviciodecomunicacinparalosclientesyterminales.Aunquelas
redespblicas,endiferentespases,sonengeneral,muydiferentesencuantoasu
estructura interna, todas ellas utilizan el modelo OSI y las normas CCITT o los
protocolosOSIparatodaslascapas.
CSENETrealmente,CSNETnoesunaredrealcomoARPANET,sinomsbienesuna
metared que utiliza los servicios de transmisin brindados por otras redes y aade
una capa protocolo uniformadora en la parte superior, para hacer que todo ello
parezcacomounasolaredlgicaparalosusuarios.
BITNETseinicienelao1981poriniciativadelaUniversidaddeNuevaYorkydela
UniversidaddeYale.Laideaporlaquesemontestaredfuelacreacindeunared
universitaria,parecidaaCSNET,queincluyeratodoslosDepartamentosdelamisma.
Estaseextendienalrededorde150localidadesdeEstadosUnidosyentre260de
Europa,atravsdesuequivalentedenominadaEARN,denominadaRedEuropeade
InvestigacinAcadmica(REIA).
USENET esta red fue desarrollada en las Universidades de Duke y North Carolina,
ofreceunserviciodereddenoticiasparalossistemasUNIX.Lasnoticiasporredse
dividenencientosdegruposdenoticiasconunagrandiversidaddetemas,algunos
de ellos son de carcter tcnico y otros no. Los usuarios de USENET se pueden
subscribiracualquiergrupoquelesinterese.
SNAeslaarquitecturaderedesdeIBM,ysetraduceporArquitecturadeRedesde
Sistemas.ElmodeloOSIseconfigurtomandocomobaselaredSNA,incluyendoel
concepto de estratificacin, el nmero de capas seleccionadas y sus funciones
aproximadas. SNA es una arquitectura de red que permite que los clientes de IBM
construyan sus propias redes privadas, tomando en cuenta a los hosts y la subred.
AunqueesposiblellevaracabounacorrespondenciaaproximadadelascapasSNA
conlascapasdelmodeloOSI,siseobservacondetalle,sepuedeapreciarquelosdos
modelosnotienenunacorrespondenciacompleta,especialmenteenlascapas3,4y
5.
INTERNET:Redderedes.Sehablaextensamentedeellaenelapartadosiguiente.
ElprotocoloTCP/IP(TransmissionControlProtocol/InternetProtocol,ProtocolodeControlde
Transmisin/ProtocolodeInternet)proporcionaunsistemaindependientedeintercambiode
datosentreordenadoresyredeslocalesdedistintoorigen,[Comer96],[Orfali98],y[Hahn
94]. Este protocolo ha evolucionado hasta nuestros tiempos a pesar de que han aparecido
otros como el ATM (Asynchronous Transfer Mode, Modo de Transferencia Asncrono), que
handemostradosermspotentesperomenosdifundidos.
Las funciones propias de una red de computadoras pueden ser divididas en las siete capas
propuestas por ISO para su modelo de referencia OSI; sin embargo la implantacin real de
unaarquitecturapuedediferirdeestemodelo.LasarquitecturasbasadasenTCP/IPproponen
cuatro capas en las que las funciones de las capas de sesin y presentacin son
responsabilidaddelacapadeaplicacinylascapasdeenlaceyfsicasonvistascomolacapa
deInterfazalaRed.Portalmotivo,paraTCP/IPsloexistenlascapasInterfazdeRed,lade
Intercomunicacin en Red, la de Transporte y la de Aplicacin. Como puede verse TCP/IP
presuponeindependenciadelmediofsicodecomunicacin,sinembargoexistenestndares
biendefinidosalosnivelesdeenlacededatosyfsicoqueproveenmecanismosdeaccesoa
los diferentesmedios y queen el modeloTCP/IP debenconsiderarse la capa de Interfazde
Red;siendolosmsusualeselproyectoIEEE802,Ethernet,TokenRingyFDI.
LascuatrocapasdelmodeloTCP/IPsedescribenseguidamente:
328 PROGRAMACIN C++ Y COMUNICACIONES.
CapadeInterfazdeRed.Emitealmediofsicolosflujosdebitsyrecibelosque
delprovienen.Consisteenlosgestoresdelosdispositivosqueseconectanal
mediodetransmisin.
Para que en una red dos computadoras puedan comunicarse entre s ellas deben estar
identificadas con precisin Este identificador puede estar definido en niveles bajos
(identificador fsico) o en niveles altos (identificador lgico) de pendiendo del protocolo
utilizado. TCP/IP utiliza un identificador denominado direccin Internet o direccin IP, cuya
longitud es de 32 bites. La direccin IP identifica tanto a la red a la que pertenece una
computadoracomoaellamismadentrodedichared.Enlasiguientetablaseestablecenlos
diferentestiposderedesquesepuedenestablecersegnladireccinIP.
TeniendoencuentaunadireccinIPpodrasurgirladudadecmoidentificarqupartedela
direccinidentificaalaredyqupartealnodoendichared.Loanteriorseresuelvemediante
ladefinicindelas"ClasesdeDireccionesIP".Paraclarificarloanteriorpuedeversequeuna
redcondireccinclaseAquedaprecisamentedefinidaconelprimeroctetodeladireccin,la
claseBconlosdosprimerosylaCconlostresprimerosoctetos.Losoctetosrestantesdefinen
losnodosenlaredespecfica.
Las subredes tienen una gran importancia en la implantacin de redes. Estas subredes son
redesfsicasdistintasquecompartenunamismadireccinIP.Debenidentificarseunadeotra
usandounamscaradesubred.Lamscaradesubredesdecuatrobytesyparaobtenerel
nmero de subred se realiza un operacin AND lgica entre ella y la direccin IP de algn
equipo.LamscaradesubreddeberserlamismaparatodoslosequiposdelaredIP.
UnodelosinconvenientesdeestasdireccionesIPessucomplicadamemorizacinporparte
delosusuarios.Parasolucionarlo,seadoptunatabladenominadanombrededominioque
traducalasdireccionesIPaunaseriedecdigosmscomprensibles.Estopermitequeuna
direccin IP como 123.89.100.102 puede traducirse mediante la tabla de dominios en
copernico.latoa.upm.e. La primera parte del dominio indica el nombre de la mquina a
quiencorrespondeladireccinIP,enestecasocopernico;acontinuacin,vieneelnombrede
la organizacin a la que pertenece el servidor, que sera el latoa.upm; en tercer lugar, se
encuentra un cdigo que puede referirse al tipo de organizacin a la que pertenece el
sistema,oalpasdondereside.As,existencdigoscomo.gov(organismogubernamental),
.edu (universidades o centros educativos), .com (redes comerciales pertenecientes a
empresas)ocdigosdepasescomo.itparaItalia,.mxparaMxico,o.esparaEspaa.
LasdireccionesIPyfsicadelacomputadoraqueconsultaesincluidaencadaemisingeneral
ARP,elequipoquecontestatomaestainformacinyactualizasutabladeconversin.ARPes
unprotocolode bajo nivelque oculta eldireccionamiento de la reden las capas inferiores,
permitiendoasignar,anuestraeleccin,direccionesIPalosequiposenunaredfsica.
LaimplementacindelprotocoloARPrequierevariospasosquesedescribenacontinuacin.
Enprimer lugar, la interfaz de red recibeun datagrama IP a enviar a un equipodestino, en
estenivelsecotejalatablatemporaldeconversin,siexisteunalareferenciaadecuadasta
se incorpora al paquete y se enva. Si no existe la referencia un paquete ARP de emisin
general,conladireccinIPdestino,esgeneradoyenviado.Todoslosequiposenlaredfsica
reciben el mensaje general y comparan la direccin IP que contiene con la suya propia,
enviando un paquete de respuesta que contiene su direccin IP. El computador origen
actualizasutablatemporalyenvaelpaqueteIPoriginal,ylossubsecuentes,directamentea
lacomputadoradestino.
El funcionamiento de ARP no es tan simple como parece. Supngase que en una tabla de
conversinexistaunmapeodeunamquinaquehafalladoyselehareemplazadolainterfaz
dered;enestecasolospaquetesquesetransmitanhaciaellaseperdernpueshacambiado
ladireccinfsica,portalmotivolatabladebeeliminarentradasperidicamente.
Protocoloorientadoanoconexin.
Fragmentapaquetessiesnecesario.
DireccionamientomediantedireccioneslgicasIPde32bits.
Siunpaquetenoesrecibido,estepermanecerenlaredduranteuntiempo
finito.
Realizael"mejoresfuerzo"paraladistribucindepaquetes.
Tamaomximodelpaquetede65635bytes.
Slo ser realiza verificacin por suma al encabezado del paquete, no a los
datosstequecontiene
LaUnidaddeTransferenciaMximadeterminalalongitudmxima,enbytes,quepodrtener
un datagrama para ser transmitida por una red fsica. Obsrvese que este parmetro est
determinado por la arquitectura de la red: para una red Ethernet el valor de la MTU es de
1500 bytes. Dependiendo de la tecnologa de la red los valores de la MTU pueden ir desde
128hastaunoscuantosmilesdebytes.Laarquitecturadeinterconexinderedespropuesta
porTCP/IPindicaquestasdebenserconectadasmedianteunacompuerta.Sinobligaraque
la tecnologa de las redes fsicas que se conecten sea homognea. Por tal motivo si para
interconectar dos redes se utilizan medios con diferente MTU, los datagramas debern ser
fragmentadosparaquepuedansertransmitidos.Unavezquelospaqueteshanalcanzadola
redextremalosdatagramasdebernserreensamblados.
Enrutamiento de paquetes
Existendostiposdeenrutamiento;eldirectoyelindirecto.Debidoaqueenelenrutamiento
directolosdatagramassetransmitedeunequipoaotro,enlamismaredfsica,elprocesoes
muyeficiente.LavinculacinentreladireccinfsicaylaIPserealizamedianteelARP.
332 PROGRAMACIN C++ Y COMUNICACIONES.
laarquitecturadeinterconexinderedesdeTCP/IPcadaparderedesseconectanmediante
compuertas.Paraquelospaquetesalcancensusredesdestinolascompuertasdebencontar
con mecanismos mediante los cuales ntercambien la informacin de las redes que conecta
cadauno.
LaarquitecturadeenrutamientoporCompuertaNcleosebasaesdefinirunacompuertaque
centraliza las funciones de enrutamiento entre redes, a esta compuerta se le denomina
ncleo. Cada compuerta en las redes a conectar tiene como compuerta por defecto a la
compuertancleo.Variascompuertas ncleo pueden conectarse paraformar una gran red;
entrelascompuertasncleoseintercambiarinformacinconcernientealasredesquecada
una de ellas alcanzan. La arquitectura centralizada de enrutamiento fue la primera que
existi.Susprincipalesproblemasradicannotantoenlaarquitecturaens,sinoenlaforma
enquesepropagabanlasrutasentrelascompuertasncleo.
Conforme las complejidades de las redes aumentaron se debi buscar un mecanismo que
propagase la informacin de rutas entre las compuertas. Este mecanismo deba ser
automticoestoobligadoporelcambiodinmicodelasredes.Denoseraslastransiciones
entrelascompuertaspodansermuylentasynoreflejarelestadodelaredenunmomento
dado. Para resolver este problema se define el vector de distancia. Se asume que cada
compuerta comienza su operacin con un conjunto de reglas bsicas de cmo alcanzar las
redesqueconecta.Lasrutassonalmacenadasentablasqueindicanlaredylossaltospara
alcanzaresared.Peridicamentecadacompuertaenvaunacopiadelastablasquealcanza
directamente. Cuando una compuerta recibe el comunicado de la otra actualiza su tabla
Asignacindenmerosdesecuenciaalainformacinsegmentada.
Validacionesdelainformacinrecibida.
Reconocimientodepaquetesrecibidos.
Cadavezqueunpaqueteesenviadoseinicializauncontadordetiempo,alalcanzareltiempo
de expiracin, sin haber recibido el reconocimiento, el paquete se reenva. Al llegar el
reconocimiento el tiempo de expiracin se cancela. A cada paquete que es enviado se le
asignaunnmerodeidentificador,elequipoquelorecibedeberenviarunreconocimiento
334 PROGRAMACIN C++ Y COMUNICACIONES.
de dicho paquete, lo que indicar que fue recibido. Si despus de un tiempo dado el
reconocimiento no ha sido recibido el paquete se volver a enviar. Obsrvese que puede
darseelcasoenelqueelreconocimientoseaelquesepierda,enestecasosereenviarun
paqueterepetido.
Proveeunservicionoconfiableorientadoanoconexin.Elprogramadeaplicacintienela
totalresponsabilidaddelcontroldeconfiabilidad,mensajesduplicadosoperdidos,retardosy
paquetes fuera de orden. Este protocolo deja al programa de aplicacin a ser explotado la
responsabilidaddeunatransmisinfiable.Conlpuededarseelcasodequelospaquetesse
pierdan o bien no sean reconstruidos en forma adecuada. Permite un intercambio de
datagramasmsdirectoentreaplicacionesypuedeelegirseparaaquellasquenodemanden
unagrancantidaddedatagramasparaoperarptimamente.
pseudocabeceraIP
cabeceraUDP
MensajeUDP
Origen y evolucin
Para evitar que un ataque nuclear pudiera dejar aisladas a las instituciones militares y
universidades,en1969elARPA(AdvancedResearchProjectsAgency),unaagenciasubsidiaria
del Departamento de Defensa de Estados Unidos, desarroll una red denominada ARPAnet
basadaenelprotocolodeintercambiodepaquetes.
Unprotocolodeintercambiodepaquetesesunsistemaquedividelainformacinenpartesy
lasenvaunaporunaalordenadordedestinoconuncdigodecomprobacin.Sielcdigode
comprobacin no es correcto, se solicita al ordenador de destino que vuelva a enviar los
paquetescorruptos.
Otraventajaesqueestetipodesistemaspermitedistribuirmsfcilmentelosdatos,yaque
cada paquete incluye toda la informacin necesaria para llegar a su destino, por lo que
paquetes con distinto objetivo pueden compartir un mismo canal. Adems, es posible
comprimircadapaqueteparaaumentarlacapacidaddetransmisin,oencriptarsucontenido
paraasegurarlaconfidencialidaddelosdatos.Estasvirtudeshanaseguradolasupervivencia
delosprotocolosdesdelasprimeraspruebasrealizadasen1968porelLaboratorioNacional
deFsicadelReinoUnidohastanuestrosdas.
ElprimerprotocoloutilizadoporARPAnetfueeldenominadoNCP(NetworkControlProtocol,
ProtocolodeControldeRed),queseempleenlaredhasta1982.Enesteaoseadoptel
protocolo TCP/IP procedente de los sistemas Unix, que cada vez tenan ms importancia
dentrodeARPAnet.
Sinembargo,laredInternetcomoredderedesnocomenzafuncionarhastadespusde
la primera conferencia de comunicaciones por ordenador en octubre de 1972. En esta
convencin ARPAnet presentaba una red de 40 nodos y se propuso su conexin con otras
redesinternacionales.RepresentantesdevariospasesformaronaselINWG(InterNetwork
WorkingGroup)paraestablecerunprotocolocomnconelARPA,empezandoadarformalo
quehoyendaconocemosporInternet.
Con el tiempo ARPAnet fue sustituida por NSFnet, la red de la fundacin nacional para la
ciencia de EEUU, como organismo coordinador de la red central de Internet. Desde los
primeros pasos de ARPAnet, hasta hoy enda, la red hasufrido pocos cambios, comparado
con los avances de la informtica. Los cambios ms drsticos se han producido en la
infraestructura de la red, aumentando la velocidad de transmisin hasta permitir el
funcionamientodeaplicacionesmultimediaylatransmisindevdeoosonidoentiemporeal.
Tambin han sufrido cambios el tipo de servicios ofrecidos por Internet, ya que si bien las
utilidadesenmodotextohansobrevividohastanuestrosdas,laverdaderaestrelladelaRed
eslaWorldWideWeb,unserviciodeconsultadedocumentoshipertextualesquehalogrado
granpopularidadtantoentreexpertoscomoentreprofanos.
UnodeloscambiosmsespectacularesquehasufridoInterneteseldelnmerodeusuarios.
Desde los primeros tiempos de ARPAnet en los que slo una decena de ordenadores y un
centenar de usuarios tenan acceso a la red, hemos pasado a cifras importantes. Se calcula
que existen unos 4 millones de sistemas conectados actualmente a Internet, facilitando
accesoaunos50millonesdeusuariosentodoelmundo.
Lascifrassonanmssorprendentessiseconsideraqueelcrecimientoactualdelcensode
usuariosdeInternetesaproximadamentedeundiezporcientomensual.Estascifrasindican,
porejemplo,queenelsigloXXIlosusuariosdeInternetpodranalcanzarennmeroalosque
ven televisin actualmente. Esto hace que Internet se est convirtiendo en una realidad de
nuestro tiempo, y puede provocar una pequea revolucin en nuestra forma de vida, del
mismomodoquelohanhecholosordenadores,telfonosmviles,discoscompactos,etc.
Estefenmenohaatradolosinteresesdemuchasempresasdetodoslossectores,queven
enInternetunvehculoidealparaactividadescomerciales,tcnicasodemarketing,adems
deunmediodedistribucindirectadesoftware,yengeneraldeinformacindetodotipo.
CORREO ELECTRNICO
338 PROGRAMACIN C++ Y COMUNICACIONES.
Uno de los primeros servicios que la red ARPAnet incorpor desde sus inicios fue el correo
electrnico. Como el correo normal, su versin electrnica, tambin denominada email,
proporcionaunmedioparaquecualquierusuariodeunaredpuedaenviarmensajesaotras
personas.
Apesardequecadausuariopuedeestarutilizandounordenadorounaaplicacindecorreo
electrnico diferente, e incluso pertenecer a redes de ordenadores no conectadas
directamente a Internet, el protocolo utilizado SMTP (Simple Mail Transfer Protocol,
Protocolo de Transmisin de Mensajes Simples), asegura una absoluta compatibilidad en el
intercambiodemensajes.
Existen tambin otros servicios que pueden ser utilizados a travs del correo electrnico:
accesoalibrerasdesoftware,consultadeinformacinsobreciertostemas,participacinen
juegosdeestrategia,odiscusinconotrosusuariosenforostemticos.
Lasdireccionesdecorreoelectrnicoestncompuestasporunnombredeusuario,elsmbolo
@ y el nombre completo del dominio del ordenador que estamos utilizando o del
proveedordeaccesoquehemoscontratado.Sielusuarioconelquequeremoscontactarno
seencuentraenunaredunidadirectamenteaInternet,existenunastablasdeconversinque
permitirnanuestrosmensajesllegarasudestinoatravsdelasoportunaspasarelas,que
no son otra cosa que ordenadores que hacen de puente entre dos redes y que permiten
ciertointercambiodeinformacinentreellas.
Si se dispone de un acceso a Internet se puede contar con una direccin propia de correo
electrnicoyunespacio,denominadobuzn,eneldiscodelordenadorquefuncionacomo
servidordecorreo.Enesteespacioseirnalmacenandolosmensajesdecorreoelectrnico
que vayan llegando con nuestra direccin para que, cuando nos conectemos, podamos
comprobarsitenemoscorreonuevoyaccederal.Enmuchoscasoseltamaodeestebuzn
ser limitado. Al enviar o recibir un mensaje de correo electrnico debe tenerse en cuenta
que su viaje por Internet va a ser ms lento que con otro tipo de servicios, ya que tiene
asignadounanchodebandamenorqueeldeotrosdeaccesodirecto.
calidad adems de una gran flexibilidad, a pesar del inconveniente de su escasa rapidez de
transmisin.
TELNET
ElprogramaTelnetpermiteaccedermedianteunterminalvirtualaunamquinaconectadaa
Internet,siemprequeseconozcasudireccinIP,onombrededominio,ysedispongadeun
nombre de usuario y la correspondiente clave de acceso. Segn sea el sistema al que se
accede, se tendr que utilizar un tipo de terminal distinto. Los ms habituales son el vt100
paramquinasUnixoVAXyelANSIparaPCs.
UnaimagendelprogramaTELNETsobreWindowssepuedeobservarenlafigura3.5.Parala
conexinconlaotramquinadeberemosintroducirelNombredehostosudireccinIP,el
PuertoporelqueserealizarlaconexinyelTipodeterminal.
grficos y con posibilidad de usar el ratn, mientras que el Telnet slo puede funcionar en
modotexto.Sinembargo,ansonmuchoslosserviciosqueseofrecenmedianteTelnetpara
losnostlgicosdelosterminalesdetexto,yentodocasosuutilidadcomoherramientapara
trabajardesdecasasiguesiendoimportante.
FTP
EsteesotrodelosserviciosmspopularesdentrodeInternetysiguesiendounodelosms
tilesalahoradetransmitirorecibirficherosdecualquiertipo.ElFTP(FileTransferProtocol,
Protocolo de Transferencia de Ficheros). Es un programa que funciona con el protocolo
TCP/IP y que permite acceder a un servidor de este sistema de intercambio para recibir o
transmitirarchivosdetodotipo.
Ademsdeconocerladireccindelamquinadelaquesequiereextraerficheros,tambin
esnecesarioasegurarsedequeeneseordenadorestfuncionandounprogramademonio
oservidordeFTP.Enelcasodequeexista,tendremosqueconocerunnombredeusuarioy
unaclavedeaccesovlidos,amenosqueelservidorpermitaefectuarFTPannimos.
ExistenmultituddesistemasalolargodelareddedicadosaofrecerserviciodeFTPannimo,
poniendo a disposicin ficheros de todo tipo. Muchas empresas como Creative Labs, IBM o
Microsoftutilizanestemtodoparaofreceralosusuarioslasltimasversionesdelosdrivers
outilidadesdisponiblesparasusproductos.
Tambin existen servidores dedicados exclusivamente a recoger todo tipo de software con
licenciasharewareyfreewareparacualquiersistemaoperativo.Adems,dentrodeInternet
encontramos servidores dedicados a recoger documentos como las famosas FAQ
(FrequentlyAskedQuestions,Preguntasyrespuestashabituales),quetienenrespuestaalas
preguntasmsfrecuentesrealizadasporlosusuariosdeInternetdentrodelserviciodeNews,
olosdocumentosFYI(ForYourInformation,Informacinparausted),coninformacinde
todotiposobrelaRed.
AunqueyahanpasadomuchosaosdesdelaprimeraimplementacindelFTP,esteservicio
siguesiendoelmtododetransportededatosporexcelenciaenInternet.
LaWWWesunareddeservidoresdentrodeInternetqueofrecepginashipertextualesenun
formato denominado HTML (HyperText Markup Language, Lenguaje de Marcas de
Hipertexto).Esunlenguajededefinicindepginasconextensioneshipertextualesportable
a cualquier tipo de plataforma grfica. Estas pginas contienen, adems de texto en varios
formatos, imgenes, sonidos o vdeo, y permiten lanzar la lectura de pginas de otros
servidoresactivandociertaspalabrasresaltadasdentrodelmismodocumento.
Tanto las pginas Web como otros servicios de Internet tienen asignada su propia URL
(Uniform Resource Locator, Cdigo Uniforme de Recursos). Se trata de un cdigo que
342 PROGRAMACIN C++ Y COMUNICACIONES.
contienelaidentificacindelservicio,ladireccindelservidorysiesnecesarioeldirectorio
dondeseencuentranlosficherosnecesariosdentrodelsistemaremoto.
As,unaURLdelaformahttp://www.mec.esindicaquequeremosconsultarunapginade
WorldWideWebenformatohttp(HyperTextTransferProtocol,ProtocolodeTransferencia
de Hipertexto). En el servidor de direccin de dominio completa www.mec.es. Si
quisiramosrealizarunFTP,laURLseraporejemploftp://ftp.microsoft.com/pub,donde
ftp.microsoft.com es la direccin del servidor y /pub es el directorio donde se
encuentranlosficherosquenosinteresan.
El lenguaje HTML
NavegarporInternetmedianteunprogramaclientedeWorldWideWebseconvierteenuna
tareasumamentesencillayagradable,aprovechandotodaslasposibilidadesdelaRed.Esta
sensacin ha sido aumentada considerablemente gracias a empresas como Netscape, que
han desarrollado programas cliente realmente amistosos con el usuario y de muy sencillo
manejo,incorporandomultituddeutilidadesparafacilitarlaexploracindelaRed.
Todas estas virtudes son posibles gracias al lenguaje HTML propuesto por vez primera, en
marzo del ao 1989, en los laboratorios de investigacin de fsica de partculas de Suiza, el
CERN. Esta institucin encarg a uno de sus departamentos el desarrollo de un sistema de
lecturadedocumentosquefacilitaraladivulgacincientfica,[Alvarez97],[Musciano98]
Nofuesinohastaelao1990,cuandoelproyectodeestaprestigiosainstitucin,recibiel
nombredefinitivodeWorldWideWeb.Afinalesdeesemismoaoempezaronafuncionar
lasprimerasversionesdelsistemaenplataformasNeXT.Apartirdelapresentacindeeste
prototipo en determinadas convenciones y especialmente en un seminario que ofreci el
propioCERN,enjuniode1991,muchasinstitucionesseinteresaronporelproyecto.
En1994,aodelaprimeraconferenciainternacionaldeWorldWideWeb,yaseencontraban
registrados oficialmente unos 1.500 servidores de este sistema. En la actualidad se calcula
quelosservidoresdeestetipopuedenllegaraservariasdecenasdemiles,aunqueelclculo
probablementesequedecortodadaladificultaddelrecuentoporelrpidocrecimientodel
nmerodeellos.
Desde que el CERN sacara a la luz su primera especificacin, el lenguaje HTML fue
adquiriendo cada vez ms posibilidades, incorporando capacidades multimedia y ms
recientementelaposibilidaddecrearpginasentresdimensiones.Casisindarsecuentalos
responsables del CERN haban creado uno de los fenmenos de mayor repercusin en
Internetalolargodesuhistoria.
Gracias a estas facilidades proporcionadas por el lenguaje muchas otras empresas han
empezadoadesarrollarmultituddeappletscondistintasfunciones.Unappletesunpequeo
programaejecutablequeenvaelservidoralprogramaclienteparaquefuncioneincorporado
alapgina.
344 PROGRAMACIN C++ Y COMUNICACIONES.
De esta manera, aunque el lector de pginas no incorpore ciertas funciones, stas pueden
aadirsedesdeelservidorparaquepuedaleer,porejemplo,diversosformatosmultimedia
sinincorporarenelmismoprogramaellectorparadichosdocumentos.
Aplicaciones externas
Ademsdelosapplets,muchasempresasydesarrolladoresindependienteshandesarrollado
aplicaciones externas que proporcionan a los navegadores ms posibilidades. Mediante
ciertasaplicacionessepuedeescucharsonidoenvivoovertelevisinatravsdeunapgina
deWeb.
Entre las aplicaciones accesorias que han sido desarrolladas ltimamente encontramos
aquellas que permiten hablar y recibir sonido a travs de Internet. Estos programas
convierten nuestro ordenador en un verdadero telfono digital de cobertura mundial con
funcionesinteresantesyunahorroconsiderableenllamadasinternacionales.
La ventaja de los applets frente a este tipo de aadidos es que se cargan mientras se est
consultandolapginayluegosonborradosdeldiscolocal.Adems,sielpropioservidoresel
queproporcionalaaplicacinparareproducirlosficherosquecontiene,lacompatibilidadde
mediosestasegurada.
Para sacar el mximo partido a la navegacin por la World Wide Web es aconsejable
conseguir un navegador de 32 bits que pueda funcionar en cualquiera de los sistemas
operativos de la actualidad que admitan multitarea. De esta manera podemos esperar la
cargadeunapginadeWeb,mientrasnosocupamosdeotrascosas,einclusoutilizaralavez
otroservicioInternetparanodesperdiciarelanchodebandadelacomunicacin.
Algunos de los navegadores, como es el caso de la ltima versin del Netscape Navigator,
incorporanherramientasparaelusodeotrosserviciosdeInternetcomocorreoelectrnicoo
News,facilitandolainteraccinconlaRed.
Ademsdelasfuncionesdelospropiosnavegadores,hayquetenerencuentalasmltiples
utilidades que ofrecen los servidores de WWW. Las ms tiles y populares son las
herramientas de bsqueda por la Red, que mediante determinados criterios y consultando
unabasededatosdedireccionesdepginasmsomenosextensanosofrecenunalistade
direccionesquecumplenconloscriteriosquehemosespecificado.
Navegadores.
DesdequedierasusprimerospasosenellaboratoriosuizodefsicanucleardelCERNallpor
elao1989,laWorldWideWebhaexperimentadounespectacularaumento,tantoenoferta
de servidores,como ennmero de usuarios, convirtindose sin lugar adudas en el servicio
mspopulardentrodeInternet,sobretodoporlafacilidaddeaccesoalosrecursosdelared.
LaWorldWideWeb,porsupropiaestructura,tienelavirtuddeconvertirlaexploracinde
Internet en una tarea sencilla y agradable, ya que ofrece la posibilidad de acceder a gran
cantidaddeinformacindeunamaneraintuitivamedianteunsistemadeconsultabasadoen
unentornogrfico.Sinembargo,esteconjuntodeposibilidadesslosonaccesiblesatravs
del programa adecuado, se precisa de un navegador, o programa cliente que sea capaz de
interpretarellenguajededescripcindepginaqueutilizalaWWW.
Casi todas estas aplicaciones son de libre distribucin para la mayora de las plataformas,
utilizando entornos grficos tan extendidos como XWindow y Windows. La utilizacin del
346 PROGRAMACIN C++ Y COMUNICACIONES.
Dehecho,existeunagrandiferenciaentreexplorarlaredconunbuenprogramaclientede
WWWqueabarquetodaslasposibilidadesdellenguajededescripcinHTMLyqueaadasus
propiasutilidades,arealizarestamismaoperacinconunprogramademenorsofisticacin
tcnicaquepuederecortarsensiblementelasposibilidadesdelsistema.
Como se ha visto en el captulo anterior, para que varios ordenadores se comuniquen entre s, es
claro que deben estar de acuerdo en cmo transmitirse informacin, de forma que cualquiera de
ellos pueda entender lo que estn transmitiendo los otros, de la misma forma que nosotros nos
ponemos de acuerdo para hablar en ingls cuando uno es italiano, el otro francs, el otro espaol y
el otro alemn.
Al "idioma" que utilizan los ordenadores para comunicarse cuando estn en red se le
denomina protocolo. Como se ha visto, hay muchos protocolos de comunicacin, entre los cuales el
ms extendido es el TCP/IP porque entre otras cosas es el que se utiliza en Internet.
De hecho, tanto en Linux/Unix como en Windows contamos con serie de libreras que nos permiten
enviar y recibir datos de otros programas, en C/C++ o en otros lenguajes de programacin, que
estn corriendo en otros ordenadores de la misma red.
En este captulo se presenta una introduccin a los sistemas distribuidos, los servicios
proporcionados en POSIX para el manejo de Sockets, que son los conectores necesarios (el recurso
software) para la comunicacin por la red, y su uso en nuestra aplicacin. No pretende ser una gua
exhaustiva de dichos servicios sino una descripcin prctica del uso ms sencillo de los mismos, y
como integrarlos en nuestra aplicacin para conseguir nuestros objetivos. De hecho, en el curso del
captulo se desarrolla una clase C++ que encapsula los servicios de Sockets, permitiendo al usuario
un uso muy sencillo de los mismos que puede valer para numerosas aplicaciones, aunque
obviamente no para todo.
Desdeelpuntodevistadeprogramacin,unsocketnoesmsqueun"fichero"queseabre
de una manera especial. Una vez abierto se pueden escribir y leer datos de l con las
habitualesfuncionesderead()ywrite()dellenguajeC.Hablaremosdetodoestocondetalle
msadelante.
Enelprimercasoambosprogramasdebenconectarseentreellosconunsocketyhastaque
no est establecida correctamente la conexin, ninguno de los dos puede transmitir datos.
Esta es la parteTCPdelprotocoloTCP/IP, y garantizaque todos losdatos van a llegar deun
programaalotrocorrectamente.Seutilizacuandolainformacinatransmitiresimportante,
no se puede perder ningn dato y no importa que los programas se queden "bloqueados"
esperandoo transmitiendodatos. Si unode los programas est atareado en otracosa yno
atiende la comunicacin, el otro quedar bloqueado hasta que el primero lea o escriba los
datos.
Enesteejemplo,elservidordepginaswebsellamaservidorporqueest(odeberadeestar)
siempre encendido y pendiente de que alguien se conecte a l y le pida una pgina. El
navegadordeInterneteselcliente,puestoquesearrancacuandonosotrosloarrancamosy
solicitaconexinconelservidorcuandonosotrosescribimosenlabarradelnavegador,por
ejemplo,http://www.elai.upm.es.com
En los juegos de red, por ejemplo el Age of Empires, debe haber unservidorque es el que
tiene el escenario del juego y la situacin de todos los jugadores en l. Cuando un nuevo
jugador arranca el juego en su ordenador, se conecta al servidor y le pide el escenario del
juegoparapresentarloenlapantalla.Losmovimientosquerealizaeljugadorsetransmitenal
servidoryesteactualizaescenariosatodoslosjugadores.
EL SERVIDOR
ApartirdeestepuntocomenzamosconloqueeslaprogramacinenC/C++delossockets.
Unavezincluidaeinicializadalalibreradesockets(pasoquehayquehacerenWindows,no
asenLinux)enClospasosquedebeseguirunprogramaservidorsonlossiguientes:
Avisaralsistemaoperativodequehemosabiertounsocketyqueremosqueasocie
nuestroprogramaadichosocket.Seconsiguemediantelafuncinbind().Elsistema
todava no atender a las conexiones de clientes, simplemente anota que cuando
empiece a hacerlo, tendr que avisarnos a nosotros. Es en esta llamada cuando se
debeindicarelnmerodepuertoalquesequiereatender.
Avisar al sistema de quecomience a atender dicha conexinde red. Se consigue
mediantelafuncinlisten().Apartirdeestemomentoelsistemaoperativoanotar
la conexin de cualquier cliente para pasrnosla cuando se lo pidamos. Si llegan
clientes ms rpido de lo que somos capaces de atenderlos, el sistema operativo
haceuna"cola"conellosynoslosirpasandosegnvayamospidindolo.
Pedir yaceptar las conexionesde clientes al sistema operativo. Para ello hacemos
unallamadaalafuncinaccept().Estafuncinleindicaalsistemaoperativoquenos
dalsiguienteclientedelacola.Sinohayclientessequedarbloqueadahastaque
algnclienteseconecte.
Escribir y recibir datosdel cliente, por medio de las funcioneswrite()yread(), que
son exactamente las mismas que usamos para escribir o leer de un fichero.
Obviamente,tantoclientecomoservidordebensaberqudatosesperanrecibir,qu
datosdebenenviaryenquformato.
Cierre de la comunicaciny del socket, por medio de la funcinclose(), que es la
mismaquesirveparacerrarunfichero.
EL CLIENTE
Lospasosquedebeseguirunprogramaclientesonlossiguientes:
Aperturadeunsocket,comoelservidor,pormediodelafuncinsocket()
Solicitar conexinconel servidor por medio de la funcinconnect(). Dicha funcin
quedarbloqueadahastaqueelservidoraceptenuestraconexinobiensinohay
servidorenelsitioindicado,saldrdandounerror.Enestallamadasedebefacilitar
ladireccinIPdelservidoryelnmerodepuertoquesedesea.
Escribiryrecibirdatosdelservidorpormediodelasfuncioneswrite()yread().
Cerrarlacomunicacinpormediodeclose().
Acontinuacinsepresentaelcdigodeunprogramaclienteydeunprogramaservidor,para
describir breve y generalmente los servicios de sockets implicados. Este cdigo es
prcticamente el ms bsico posible, sin comprobacin de errores. El funcionamiento ser
como sigue: Primero se arranca el programa servidor, que inicializa el socket servidor y se
quedaalaesperadeunaconexin.Acontinuacinsedebelanzarelprogramaclientequese
conectar al servidor. Una vez que ambos estn conectados, el servidor enviara al cliente
unosdatos(unafrase)queelclientemostrarporpantalla,yfinalmenteterminarnambos
programas.Elfuncionamientoenlneasgeneralesquedarepresentadoenlasiguientefigura:
Programa cliente
Elcdigodelprogramacliente,mssimplequeeldelservidor,eselsiguiente:
#define INVALID_SOCKET -1
int main()
{
//declaracion de variables
int socket_conn;//handle del socket utilizado
struct sockaddr_in server_address;
char address[]="127.0.0.1";
int port=12000;
// Configuracion de la direccion IP de connexion al servidor
352 PROGRAMACIN C++ Y COMUNICACIONES.
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(address);
server_address.sin_port = htons(port);
//creacion del socket
socket_conn=socket(AF_INET, SOCK_STREAM,0);
//conexion
int len= sizeof(server_address);
connect(socket_conn,(struct sockaddr *) &server_address,len);
//comunicacion
char cad[100];
int length=100; //lee un mximo de 100 bytes
int r=recv(socket_conn,cad,length,0);
std::cout<<"Rec: "<<r<<" contenido: "<<cad<<std::endl;
//cierre del socket
shutdown(socket_conn, SHUT_RDWR);
close(socket_conn);
socket_conn=INVALID_SOCKET;
return 1;
}
Acontinuacinsedescribebrevementeelprograma:
Lasprimeraslneassonalgunos#includesnecesariosparaelmanejodeserviciosdesockets.
EnelcasodequererutilizarlossocketsenWindows,elficherodecabeceraylalibreraconla
quehayqueenlazarsepodranestablecerconlaslneas:
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")
Enlasprimeraslneasdelmain()sedeclaranlasvariablesnecesariasparaelsocket.
Lasegundadeclaracindeclaraunaestructuradedatosquesirveparaalmacenarladireccin
IP y el nmero de puerto del servidor y la familia de protocolos que se utilizaran en la
comunicacin.Comoyasehaexplicado,unordenadorpuedecomunicarsesimultneamente
con muchos programas y muchos ordenadores. De alguna forma el puerto es como una
extensin a la direccin IP. Haciendo una analoga, la direccin podra entenderse como la
direccindelaescuela,mientrasqueelpueetoesundespachooextensindeterminado.La
asignacindeestaestructuraapartirdelaIPdefinidacomounacadenadetextoyelpuerto
definidocomounenterosehacecomosigue:
char address[]="127.0.0.1";
int port=12000;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(address);
server_address.sin_port = htons(port);
NtesequelaIPqueutilizaremosserla127.0.0.1.EstaIPesunaIPespecialquesignificala
mquina actual (direccin local). Realmente ejecutaremos las dos aplicaciones (cliente y
servidor)enlamismamquina,utilizandoladireccinlocaldelamisma.Noobstanteestose
puedecambiar.ParaejecutarelservidorenunamquinaquetienelaIP192.168.1.13por
ejemplo, basta poner dicha direccin en ambos programas, ejecutar el servidor en esa
mquina,yelclienteencualquierotra(queseacapazdeenrutarmensajeshaciaesaIP).
Tambin es posible utilizar funciones del sistema operativo para intentar obtener una
direccinIPenbasealconocimientodelosnombresdelosordenadores.
Hay dos ficheros en Unix/Linux y en Windows que nos facilitan esta tarea, aunque hay que
tenerpermisosderootparamodificarlos.Estosficherosseranelequivalenteaunaagenda
de telfonos, en uno tenemos apuntados el nombre de la empresa con su nmero de
telfonoyenelotroficheroelnombredelapersonaysuextensin(UPMEUITI,tlfn91336
6799;MiguelHernando,extensin6878;...)
Note que para iniciar un tipo de comunicacin mediante un socket se requiere designar un
puerto de comunicaciones. Esto significa que algunos puertos deben reservarse para stos
usosbienconocidos.
01023:Estospuertospuedensersloenlazadosporelsistema.
10245000:Puertosdesignadosaaplicacionesconocidas.
500164K1:Puertosdisponiblesparausosparticulares.
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users #Active users
systat 11/udp users #Active users
daytime 13/tcp
daytime 13/udp
qotd 17/tcp quote #Quote of the day
qotd 17/udp quote #Quote of the day
chargen 19/tcp ttytst source #Character generator
chargen 19/udp ttytst source #Character generator
ftp-data 20/tcp #FTP, data
ftp 21/tcp #FTP. control
ssh 22/tcp #SSH Remote Login Protocol
telnet 23/tcp
smtp 25/tcp mail #Simple Mail Transfer Protocol
time 37/tcp timserver
time 37/udp timserver
rlp 39/udp resource #Resource Location Protocol
nameserver 42/tcp name #Host Name Server
nameserver 42/udp name #Host Name Server
nicname 43/tcp whois
domain 53/tcp #Domain Name Server
domain 53/udp #Domain Name Server
bootps 67/udp dhcps #Bootstrap Protocol Server
bootpc 68/udp dhcpc #Bootstrap Protocol Client
tftp 69/udp #Trivial File Transfer
gopher 70/tcp
finger 79/tcp
http 80/tcp www www-http #World Wide Web
hosts2-ns 81/tcp #HOSTS2 Name Server
hosts2-ns 81/udp #HOSTS2 Name Server
kerberos 88/tcp krb5 kerberos-sec #Kerberos
kerberos 88/udp krb5 kerberos-sec #Kerberos
hostname 101/tcp hostnames #NIC Host Name Server
Se puede observar como el protocolo http del navegador aparece reflejado en el conocido
puerto80,ocomoelprotocolosmtpserealizaenprincipiosobreelpuerto25.
ElprimerparmetroesAF_INEToAF_UNIXparaindicarsilosclientespuedenestarenotros
ordenadoresdistintosdelservidorovanacorrerenelmismoordenador.AF_INETvalepara
losdoscasos.AF_UNIXsloparaelcasodequeelclientecorraenelmismoordenadorqueel
servidor,peroloimplementadeformamseficiente.SipusieramosAF_UNIX,elrestodelas
funcionesvaranligeramente.
Elsegundoparmetroindicasielsocketesorientadoaconexin(SOCK_STREAM)TCP/IPono
loes(SOCK_DGRAM)UDP/IP.DeestaformapodremoshacersocketsderedodeUnixtanto
orientadosaconexincomonoorientadosaconexin.
Eltercerparmetroindicaelprotocoloaemplear.Habitualmentesepone0,locualsignifica
queelsistemaloescogerpordefecto.
Ennuestrocasovamosautilizarcomunicacinorientadaalaconexinyportantofiable.
//creacion del socket
socket_conn=socket(AF_INET, SOCK_STREAM,0);
Estafuncingeneralmentenoproduceerrores,aunqueenalgncasopodrahacerlo.Como
reglageneralconvienecomprobarsuvalor,queseriguala1(INVALID_SOCKET)silafuncin
hafallado.
Acontinuacinseintentalaconexinconelsocketespecificadoenladireccindelservidor.
Comoseobservaenelejemplo,estadireccinvienedadaporunaestructuraqueyacontiene
enelformatopropiodelaredladireccin,elpuertoyelprotocolodered.Loscamposque
obligatoriamentehayquerellenarsonlosreflejadosenelejemplo:
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(address);
server_address.sin_port = htons(port);
sin_familyeseltipodeconexin(porredointerna),igualqueelprimerparmetro
desocket().
sin_portes el nmero de puerto correspondiente al servicio que podriamos haber
obtenidocongetservbyname().Elvalorestaraenenelcampos_portdePuertode
laestructuradevueltaporgetserbyname().Enelejemplosinembargoseespecifica
el nmero de puerto directamente, pero convirtindolo al formato
Finalmentesin_addr.s_addresladireccindelclientealquequeremosatender
356 PROGRAMACIN C++ Y COMUNICACIONES.
Paraentenderelusodehtonsyinet_addr,esnecesarioindicarcomoesimportantequeenla
redseenvienlosdatosconunformatoclaro.Lasmquinasenfuncindelaarquitecturayel
procesador utilizan un modo diferente de representar los nmeros. inet_addr, adems de
conseguirqueladireccinquederepresentadaconunordendebytescorrecto,loquelogra
es traducir una direccin IP dada como una secuencia de caracteres en un long int de 32
bytes.
NetworkbyteorderyHostbyteordersondosformasenlasqueelsistemapuedealmacenar
los datos en memoria. Est relacionado con el orden en que se almacenan los bytes en la
memoriaRAM.
Sialalmacenarunshortint(2bytes)ounlongint(4bytes)enRAM,yenlaposicinmsalta
sealmacenaelbytemenossignificativo,entoncesestennetworkbyteorder,casocontrario
eshostbyteorder.
Cuando enviamos los datos por la red deben ir en un orden especificado, sino enviaramos
todos los datos al revs. Lo mismo sucede cuando recibimos datos de la red, debemos
ordenarlosalordenqueutilizanuestrosistema.Debemoscumplirlassiguientesreglas:
Todoslosbytesquesetransmitenhacialared,seannmerosIPodatos,debenestar
ennetworkbyteorder.
Todoslosdatosqueserecibendelared,debenconvertirseahostbyteorder.
Pararealizarestasconversionesutilizamoslasfuncionesquesedescribenacontinuacin.
htons()hosttonetworkshortconvierteunshortintdehostbyteorderanetwork
byteorder(eselcasodelnmerodeservicioopuerto).
htonl()hosttonetworklongconvierteunlongintdehostbyteorderanetwork
byteorder.
ntohs()networktohostshortconvierteunshortintdenetworkbyteorderahost
byteorder.
ntohl()networktohostlongconvierteunlongintdenetworkbyteorderahost
byteorder.
Puede ser que el sistema donde se est programando almacene los datos en network byte
order y no haga falta realizar ninguna conversin, pero si tratamos de compilar el mismo
cdigofuenteenotraplataformahostbyteordernofuncionar.Comoconclusin,paraque
nuestrocdigofuenteseaportablesedebeutilizarsiemprelasfuncionesdeconversin.
//conexion
int len= sizeof(server_address);
connect(socket_conn,(struct sockaddr *) &server_address,len);
Estafuncinconnect()fallarsinoestaelservidorpreparadoporalgnmotivo(loquesucede
muy a menudo). Por lo tanto es ms que conveniente comprobar el valor de retorno de
connect()paraactuarenconsecuencia.Sepodrahaceralgocomo:
if(connect(socket_conn,(struct sockaddr *)
&server_address,len)!=0)
{
std::cout<<"Client could not connect"<<std::endl;
return -1;
}
Si la conexin se realiza correctamente, el socket ya esta preparado para enviar y recibir
informacin.
Enestecasohemosdecididoquevaaserelservidorelqueenvadatosalcliente.Estoesun
convenio entre el cliente y el servidor, que adopta el programador cuando disea e
implementaelsistema.
Comoelclientevaarecibirinformacin,utilizamoslafuncinderecepcin.Enestafuncin,
selesuministraunbufferenelqueguardalainformacinyelnmerodebytesmximoque
seesperarecibir.Lafuncinrecv()sebloqueahastaqueelservidorenvealgunainformacin.
Dichainformacinpuedesermenorqueeltamaomximosuministrado.Elvalorderetorno
delafuncinrecv()eselnumerodebytesrecibidos.
358 PROGRAMACIN C++ Y COMUNICACIONES.
//comunicacion
char cad[100];
int length=100; //read a maximum of 100 bytes
int r=recv(socket_conn,cad,length,0);
std::cout<<"Rec: "<<r<<" contenido: "<<cad<<std::endl;
Porultimosecierralacomunicacinysecierraelsocket.
shutdown(socket_conn, SHUT_RDWR);
close(socket_conn);
socket_conn=INVALID_SOCKET;
Servidor
El cdigo del programa servidor es algo ms Complejo, ya que debe realizar ms tareas. La
principalcaractersticaesqueseutilizandossocketsdiferentes,unoparalaconexinyotro
paralacomunicacin.ElservidorcomienzaenlazandoelsocketdeconexinaunadireccinIP
y un puerto (siendo la IP la de la mquina en la que corre el servidor), escuchando en ese
puertoyquedandoalaesperaAcceptdeunaconexin,enestadodebloqueo.Cuandoel
clienteseconecta,elAcceptsedesbloqueaydevuelveunnuevosocket,queesporelque
realmenteseenvanyrecibendatos.
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>
#define INVALID_SOCKET -1
int main()
{
int socket_conn=INVALID_SOCKET;//used for communication
int socket_server=INVALID_SOCKET;//used for connection
struct sockaddr_in server_address;
struct sockaddr_in client_address;
// Configuracion de la direccion del servidor
char address[]="127.0.0.1";
int port=12000;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(address);
server_address.sin_port = htons(port);
//creacion del socket servidor y escucha
socket_server = socket(AF_INET, SOCK_STREAM, 0);
int len = sizeof(server_address);
int on=1; //configuracion del socket para reusar direcciones
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//escucha
Lasegundadiferenciaesqueenvezdeintentarlaconexinconconnect(),elservidordebe
establecerprimeroenquedireccinvaaestarescuchandosusocketdeconexin,loquese
establececonlaslneas:
Lallamadaabind()llevatresparmetros:
Handledelsocketquehemosabierto
360 PROGRAMACIN C++ Y COMUNICACIONES.
PunteroalaestructuraDireccion.Adiferenciadeloqueocurraconelcliente,enel
casodelservidorseespecificaladireccindelclientealquequeremosatender.En
este campo introducimos INADDR_ANY, si queremos atender a un cliente
cualquiera. La estructura admitida por este parmetro es general y valida para
cualquiertipodesocketyesdeltipostructsockaddr.Cadasocketconcretollevasu
propia estructura. LosAF_INETcomo este caso llevanstruct sockaddr_in,
losAF_UNIXllevan la estructurastruct sockaddr_un. Por eso, a la hora de pasar el
parmetro,debemoshacerun"cast"altipostructsockaddr.
LongituddelaestructuraDireccion.
Estafuncintambinessusceptibledefallo.Elfallomscomnescuandoseintentaenlazar
elsocketconunadireccinypuertoqueyaestnocupadosporotrosocket.Enestecasola
funcindevolver1,indicandoelerror.Avecesesposiblequesinosecierracorrectamente
unsocket(porejemplo,sielprogramafinalizabruscamente),elSOpiensequedichopuerto
estaocupado,yalvolveraejecutarelprograma,elbind()falle,noteniendosentidocontinuar
laejecucin.Lagestinbsicadeesteerrorpodraser:
if(0!=bind(socket_server,(struct sockaddr *)
&server_address,len))
{
std::cout<<Fallo en el Bind()<<std::endl;
return -1;
}
Lafuncinlisten()permitedefinircuantaspeticionesdeconexinalservidorsernencoladas
por el sistema. Ntese que esto no significa que realmente se atiendan las peticiones de
conexin.Eselusuarioatravsdelafuncinaccept()elqueaceptaunaconexin.Elnumero
deconexionesdependerdecuantasvecesejecuteelprogramadichoaccept().
Lo ms importante del accept() es que en su modo normal bloquea el programa hasta que
realmenteserealizalaconexinporpartedelcliente.Aestafuncinselesuministraelsocket
de conexin, y devuelve el socket que realmente se utilizar para la comunicacin. Si algo
falla en la conexin, la funcin devolver 1, lo que corresponde a nuestra definicin de
socketinvalidoINVALID_SOCKET,loquepodemoscomprobar:
if(socket_conn==INVALID_SOCKET)
{
std::cout<<Error en el accept<<std::endl;
return -1;
}
Una vez que se ha realizado la conexin, la comunicacin se hace por el nuevo socket,
utilizandolasmismasfuncionesdeenvoyrecepcinquesepodranusarenelcliente.Notese
que un modo de atender a varios clientes, es ir haciendo accepts consecutivos y creando
sockets de comunicacin hasta alcanzar un nmero determinado, momento en el que ya
trabajamosconlascomunicacionesalosdistintosclientes.
Enelejemploactual,realmentesloatendemosaunclientecadavezyporconveniohemos
establecidoqueserelservidorelqueenvaunprimermensajealcliente.Elcdigosiguiente
envaelmensajeHolaMundoporelsocket:
Lafuncinsend()tambinpuedefallar,sielsocketnoestacorrectamenteconectado(seha
desconectado el cliente por ejemplo). La funcin devuelve el nmero de bytes enviados
correctamente o 1 en caso de error. Tpicamente, si la conexin es buena, la funcin
devolvercomoretornounvalorigualalength,aunquetambinesposiblequenoconsiga
enviartodoslosdatosqueselehasolicitado.Unasolucincompletadebecontemplaresta
posibilidad y reenviar los datos que no han sido enviados. No obstante y por simplicidad,
realizamosahoraunagestinsencilladeesteposibleerror:
Elcierredelossocketsserealizadelamismamaneraqueenelcliente,exceptuandoquese
deben cerrar correctamentelos dos sockets, el de conexin y el de comunicacin. La salida
por pantalla al ejecutar las aplicaciones (primero arrancar el servidor y luego el cliente)
deberaser(enelladodelcliente):
Ntese que los bytes recibidos son 11 porque incluyen el carcter nulo \0 de final de la
cadena.
Existen diversas formas de atender las conexiones de clientes en un servidor. Sin embargo
dado que la programacin concurrente no la trataremos en este curso, simplemente se
exponen a continuacin para entender la importancia de estas estructuras. La primera de
ellasrespondealmodovistoenelejemploanterios,lasegundarequieredeelusodethreads
(hilosdeejecucindeunproceso),ylaterceraeslaestructurahabitualconcomunicacinno
orientadaalaconexin.
En el siguiente grfico se muestran los procesos que se ejecutan cuando se realiza una
conexinSimpleClienteServidor:
Enelservidor:
Secreaunsocketdecomunicacinmediantelafuncinsocket().
Elsocketestformadoporunadireccinip+unpuertodeconexin,paraellohay
queasociaresainformacinalsocketmediantelafuncinbind().
Laparteservidordelaaplicacindebeestablecerunacoladeconexionesentrantes
para atender a los clientes segn el orden de llegada, esto se hace mediante la
funcinlisten().
Ahora el servidor deber atender las conexiones entrantes por el puerto que
establecimosmediantelafuncinaccept().
Tras establecer una comunicacin entre un cliente y un servidor se enviarn datos
mediantelafuncinsend()yserecibirnmediantelafuncinrecv().
Alfinalizarlacomunicacindeberemoscerrarelsocketdecomunicacin.
Enelcliente:
Secreaunsocketdecomunicacinmediantelafuncinsocket().
Elservidorestaceptandoconexionesentrantes,asquenosconectamosalservidor
mediantelafuncinconnect().
Recibimos y enviamos datos, pues ya estamos en contacto con el equipo remoto,
mediantelasfuncionesrecv()ysend().
Alfinalizarlacomunicacindeberemoscerrarelsocketdecomunicacin.
Paraentenderelmodeloconcurrente,esprecisoalmenostenerunprimerconceptodeloque
esunhilodeejecucinothread:
Concepto de thread
UnthreadeslaunidadbsicadeejecucinenlamayoradelosS.O..Cualquierprogramaque
seejecuteconstade,almenos,unthread.
siguiente.Sinembargo,estaconmutacinnosepuedehacerdecualquiermanera.Cadavez
que el S.O. se aduea de la CPU para cedersela a otro thread, los registros y la pila (o sea,
elcontextodelhilo)contienenunosvaloresdeterminados.Poreso,elS.O.guardatodosesos
datosencadacambio,demodoquealvolveraconmutaralthreadinicial,puedarestaurarel
contextoinicial.LamayoradelosS.O.multitareasondetipopreemptivo,loquesignificaque
laCPUpuedeserarrebatadaencualquiermomento.Estosignificaqueunthreadnopuede
sabercuandoselevaaarrebatarlaCPU,porloquenopuedeguardarlosregistrosnilapila
deforma'voluntaria'.
Ladiferenciamsimportanteentrehiloyproceso,consisteenquedosprocesosdistintosen
unsistemamultitarea,nocompartenrecursosnisiquieraelmapadememoria,detalforma
quelacomunicacinentrelosmismosserealizapormediodemecanismosdecomunicacin
dados por el sistema operativo (memorias compartidas, pipes, mensajes). Son como dos
instanciasdiferentesdelmismotipo.Sinembargolosthreads,salvolapilayelcontextodela
CPU,compartenrecursos,memoriaymapadedireccinesyportantolaszonasdedatosson
comunes para todos los threads de un mismoproceso. Una de las ventajas que tienen por
tanto es que la conmutacin entre hilos de un mismo programa (proceso) es muy rpida,
frentealcambiodecontextoentredosprocesos.
Por otro lado, debemos recordar que cada thread se ejecuta de forma absolutamente
independiente.Dehecho,cadaunotrabajacomosituvieseunmicroprocesadorparaelsolo.
Estosignificaquesitenemosunazonadedatoscompartidaentrevariosthreadsdemodoque
puedan intercambiar informacin entre ellos, es necesario usar algn sistema de
sincronizacinparaevitarqueunodeellosaccedaaungrupodedatosquepuedenestara
medio actualizar por otro thread. Estos problemas clsicos en los sistemas concurrentes
quedanfueradelenfoquedelcurso,perobasteaquporlomenosmencionarlo.
En el siguiente grfico se muestran los procesos que se ejecutan cuando se realiza una
conexinConcurrenteClienteServidor:
Enelservidor:
Secreaunsocketdecomunicacinmediantelafuncinsocket().
Elsocketestformadoporunadireccinip+unpuertodeconexin,paraellohay
queasociaresainformacinalsocketmediantelafuncinbind().
Laparteservidordelaaplicacindebeestablecerunacoladeconexionesentrantes
para atender a los clientes segn el orden de llegada, esto se hace mediante la
funcinlisten().
Ahora el servidor deber atender las conexiones entrantes por el puerto que
establecimosmediantelafuncinaccept().Lanicadiferenciaconelcasoanteriores
que una vez aceptada una conexin se crear un nuevo hilo de ejecucin (thread)
encargado de dicha comunicacin y en el cdigo principal se volvern a aceptar
conexiones entrantes. Esto quiere decir que por cada nueva conexin existir un
nuevothreadohilodeejecucin.
Tras establecer una comunicacin entre un cliente y un servidor se enviarn datos
mediantelafuncinsend()yserecibirnmediantelafuncinrecv().
Alfinalizarlacomunicacindeberemoscerrarelsocketdecomunicacinyfinalizar
suthreadcorrespondiente.
Enelcliente:
366 PROGRAMACIN C++ Y COMUNICACIONES.
Secreaunsocketdecomunicacinmediantelafuncinsocket().
Elservidorestaceptandoconexionesentrantes,asquenosconectamosalservidor
mediantelafuncinconnect().
Recibimos y enviamos datos, pues ya estamos en contacto con el equipo remoto,
mediantelasfuncionesrecv()ysend().
Alfinalizarlacomunicacindeberemoscerrarelsocketdecomunicacin.
En el siguiente grfico se muestran los procesos que se ejecutan cuando se realiza una
conexinClienteServidormedianteDatagrams:
Enelservidor:
Secreaunsocketdecomunicacinmediantelafuncinsocket().
Elsocketestformadoporunadireccinip+unpuertodeconexin,paraellohay
queasociaresainformacinalsocketmediantelafuncinbind().
Trasestablecerunapuertodecomunicacinquedaalasesperadedatosentrantes
mediantelafuncinrecvfrom()oenvadatosaalgnclientemediantesendto().
Alfinalizarlacomunicacindeberemoscerrarelsocketdecomunicacinyfinalizar
suthreadcorrespondiente.
Enelcliente:
Secreaunsocketdecomunicacinmediantelafuncinsocket().
El servidor ya ha establecido un puerto de comunicacin por lo que podemos
enviarle datos mediante sendto() o esperar por algn dato que el servidor desee
enviarnosmedianterecvfrom().
Alfinalizarlacomunicacindeberemoscerrarelsocketdecomunicacin.
Anexo I. Soluciones a los ejercicios.
Captulo 2
EJERCICIO2.1
EJERCICIO2.2
#include <math.h>
EJERCICIO2.3
a=3 b=5 c=6
EJERCICIO2.4
1 5 7 11 13 17 19 23 25 29
EJERCICIO2.5
OK nota1=bien;
MAL nota1=1;
OK nota1=(notas)1;
MAL nota1=suspenso+1;
MAL nota1=suspenso+aprobado;
OK var=5+bien;
OK var=bien+5;
OK var=notable+bien;
OK var=nota1+bien;
MAL nota1++;
OK for(var=suspenso;var<sobresaliente;var++)
printf(%d,var);
MAL for(nota2=suspenso;nota2<sobresaliente;nota2++)
printf(%d,(int)nota2);
EJERCICIO2.6
Valores: 18 14 17