Escolar Documentos
Profissional Documentos
Cultura Documentos
ObralicenciadasoblicenaCreativeCommonsAtribuioNoComercial
Compartilhamentopelamesmalicena2.5Brasil
ndiceAnaltico
ndice Analtico
CAPTULOI
.......................................................................................................................................................
7
EngenhariadeSoftwareEstruturada.................................................................................7
EngenhariadeSoftwareEstruturada:ousodefunes...................................................8
OC++bsico..........................................................................................................................8
Tipos:estruturas,uniesetiposenumerados.......................................................................................................8
Declarandoarrays.................................................................................................................................................8
Definindonovostipos...........................................................................................................................................8
Modificadoresdetipos.......................................................................................................................................10
Interna...........................................................................................................................................................10
Conversesdetipos............................................................................................................................................11
LaoseCondicionais..........................................................................................................................................12
Ponteiros.............................................................................................................................................................14
Umabrevediscussosobreendereosdememria............................................................................................14
Comodeclararponteiros.....................................................................................................................................14
Utilizandoponteiros...........................................................................................................................................14
Criandovariveisemtempodeexecuo:osoperadoresnewedelete.............................................................16
Ponteirosparatiposderivados............................................................................................................................17
Ponteirosearrays................................................................................................................................................17
Usandonewedeletecomarrays........................................................................................................................18
Aritmticadeponteiros......................................................................................................................................18
Ponteiroseconst.................................................................................................................................................18
Funes...............................................................................................................................................................19
Definindofunes...............................................................................................................................................19
Argumentosetiposderetornodefunes.........................................................................................................20
Ponteirosparafunes........................................................................................................................................21
Funesinline...................................................................................................................................................22
Umpoucomaissobreargumentos......................................................................................................................22
Sobrecargadefunes........................................................................................................................................24
Seoprtica:definindonossoprojeto.............................................................................25
CAPTULOII
...................................................................................................................................................
27
3
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoG.Barros
EngenhariadeSoftwareBaseadaemObjetos..................................................................27
Engenhariadesoftwarebaseadaemobjetos....................................................................28
Modularidade,coesoeacoplamento.................................................................................................................28
InformationHidding...........................................................................................................................................28
SuportemodularidadeemC++........................................................................................................................28
Suportereusabilidade:Modelosdefuno......................................................................................................30
Seoprtica:estruturandoonossoprojetoemmdulos...............................................32
CAPTULOIII
.................................................................................................................................................
33
EngenhariadeSoftwareBaseadaemClasses...................................................................33
EngenhariadeSoftwareBaseadaemClasses...................................................................34
ClassesemC++..................................................................................................................................................34
Classes:organizaoemarquivos......................................................................................................................36
Modificadoresdemtodos..................................................................................................................................37
Comocriarmembrosestticos...........................................................................................................................38
Oponteirothis....................................................................................................................................................38
Sobrecargademtodoseconstrutores................................................................................................................39
Construtoresdecpia.........................................................................................................................................39
Funes,mtodoseclassesfriend......................................................................................................................40
Conversesentreobjetos....................................................................................................................................42
Sobrecargadeoperadores...................................................................................................................................43
Modelosdeclasses.............................................................................................................................................46
Seoprtica:Criandoclassesparaojogo.......................................................................49
CAPTULOIV
..................................................................................................................................................
51
EngenhariadeSoftwareOrientadaaObjetos..................................................................51
EngenhariadeSoftwareOrientadaaObjetos..................................................................52
HeranaemC++.................................................................................................................................................52
Overloaddeconstrutores,destrutoresemtodos...............................................................................................52
Mtodosvirtuais:dynamicbinding....................................................................................................................53
Classesabstratas.................................................................................................................................................55
Heranamltipla.................................................................................................................................................56
Excees.............................................................................................................................................................58
Seoprtica:Utilizandoherana.....................................................................................61
CAPTULOV
...................................................................................................................................................
62
4
ndiceAnaltico
RecursosavanadosdoC++:RTTIeSTL......................................................................62
ARTTI(runtimetypeinformation)..................................................................................63
Ooperadordynamic_cast...................................................................................................................................63
Utilizandoooperadortypeideaclassetype_info..............................................................................................63
ASTL(standardtemplatelibrary)...................................................................................65
ContineresdaSTL............................................................................................................................................65
Iteradores............................................................................................................................................................81
AlgoritmosdaSTL.............................................................................................................................................82
Objetosfuno....................................................................................................................................................87
5
Captulo I
O C++ bsico
Tipos: estruturas, unies e tipos enumerados
Declarando arrays
Arraynadamaisdoqueumconjuntodevariveisdomesmotipoquesoacessadaspelomesmonomeeum
ndice.
Paradeclararumarraydechar,porexemplo,fazemos:
char array_de_char[20];
Ovalorentreparntesesaquantidadedeposiesqueoarraypossui,ouseja,array_de_charpossui20
variveis do tipo char. Veremos a importncia dos arrays e como utilizar arrays multidimensionais e
ponteiroscomarraysmaisadiante,nestecaptulo.
Almdostiposdedadossimplescomoint,float,double,char,...;podemosdefinirosnossoprpriostipos
dedados.Estestipossodefinidosatravsdaspalavraschavestruct,unioneenum(eposteriormente,como
veremos,class).
Estruturas
As estruturas de C++ funcionam como tipos compostos, em que se pode guardar diversas informaes
agrupadasemummesmonome.Porexemplo,paradefinirotipocompostobola,utilizamosstructdeacordo
comasintaxeabaixo:
struct TBall
{
int x;
int y;
7
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
int radius;
TColor color;
};
Abolaquedefinimostem,portanto,umaposio(x,y),umraioeumacor.Secriarmosumavariveldotipo
bola,queacabamosdedefinir,podemosacessarascaractersticasdaboladaseguinteforma:
TBall bola;
bola.x = 10;
bola.y = 15;
bola.radius = 5;
bola.color = clBlue;
Note,queTColornoumtipodedadossimples,deformaquepodemoscriartiposdedadoscompostosa
partirdeoutrostiposcompostostambm.
Unies
Uma unio um tipo composto parecido com uma estrutura. A diferena que na unio, os diversos
membroscompartilhamamesmareadememria,ouseja,alterandoummembrodaunio,narealidade
estamos alterando todos. As unies so utilizadas quando queremos acessar uma mesma informao de
diversasformas,sobreaticadediversostiposdedados,ex:
union TCharInt
{
char c;
short i;
};
int main()
{
TCharInt var;
var.c = A;
cout << O codigo ASCII da letra A e << var.i;
cin.get();
return 0;
}
Nocdigoacima,nsatribumosumaconstantedotipocharuniovar.Posteriormente,acessamosaunio
varatravsdoseumembroi,dotiposhortint.ComoaletraArepresentadainternamenteatravsdoseu
cdigo numrico, quando acessamos a varivel como um tipo short int, teremos como retorno o valor
numrico(docdigoASCII)daletraA.Portanto,oexemploacimaexibir:
Tipos enumerados
OstiposdedadosenumeradossoutilizadospararepresentartiposconceituaisquenoestopresentesnoC+
+padro.Porexemplo,pararepresentarotipodedadoscor,quepodeassumirosvaloresvermelho,verde,
azul,amarelo,ciano,magenta,brancoepreto;poderamosutilizarumtipodedadosenumerado:
8
CaptuloIEngenhariadeSoftwareEstruturada
Desta forma, as variveis do tipo TColor s aceitariam um dos valores acima, que, internamente esto
representadospornmeros,masnocdigotmumasemnticaquebastantetilparaquemforutilizar.
Modificadores de tipos
EmC++,podemosmodificaraformacomoasvariveissodeclaradasealocadas,seuescopoeasualigao
(capacidade de um item ser usado em diferentes arquivos de um mesmo programa). Isto feito com a
utilizaodosmodificadoresdetipo.Paraentendermelhoroseufuncionamento,veremosalgunsconceitos
bsicosnecessrios,antesdefalardosmodificadoresdetipospropriamenteditos.
Escopo
VariveisemC++podemterescopolocal(oudebloco)ouglobal(oudearquivo).Variveisglobaisficam
disponveisatodoocdigodoarquivo,enquantoasvariveislocaisestodisponveisapenasdentrodobloco
emqueforamcriadasenosblocosinternosaele.
Classes de armazenamento
Amemriadearmazenamento(espaoreservadosvariveis)deumprogramaemC++divididaemtrs
classes:
Ligao
Aligao(lincagem)sereferecapacidadedeumitemserutilizadoemdiversosarquivosdeumprograma.
Variveisexternas(declaradasforadequalquerfuno)possuemtambmligaoexterna,oquesignificaque
elasficamdisponveisaqualquerarquivodomesmoprograma.Jasvariveisdeligaointernasesto
disponveisnoarquivoemqueforamcriadas.
Osconceitosvistosacimaestorelacionadosdeformanosistemtica,sendosvezesdifcildeseentender
claramente. Portanto, abaixo segue uma lista das possveis associaes entre classes de armazenamento,
escopoeligao:
9
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Depoisdeentendidosestesconceitos,vamosaosmodificadorespropriamenteditos.
Modificadores:
static:utilizadoparadeclararvariveisnaclassedearmazenamentoesttico.
const:utilizadoparadeclararconstantes,que,obviamente,nopodemteroseucontedoalterado.
extern:utilizadoparaindicarqueestamosutilizandoumavarivelexterna,quefoideclaradaemoutro
arquivo.
register:utilizadoparapediraocompiladorquearmazeneavarivelemumregistradordaCPU.Isto
aceleraoacessovarivel,masnodeveserutilizadoparatodasasvariveispoisoscomputadorespossuem
geralmenteregistradoresde32bits(emalgunscomputadores,64bits),queumtamanhomenordoque
algunstiposcomodouble,eemnmerolimitado.
volatile:indicaqueumvalordeumavarivelpodeseralteradoporfatoresexternosaocdigodoprograma,
como,porexemplo,umavarivel queapontepara oendereo dorelgiodosistema,eque,portanto,
atualizada pelo hardware. Variveis em programas multithreaded1 que so alteradas e lidas em threads
diferentestambmdevemserdeclaradascomovolatile.
mutable:indicaqueummembrodeumaestrutura(ouclasse)podeseralteradomesmoquefaapartedeuma
variveldeclaradacomoconstante.
Converses de tipos
Quasesempre,emumprograma,existeanecessidadedesefazeraconversoentretiposdedadosparaquese
possarealizaroperaescomvariveisdetiposdiferentes.Aconversodetipos(outypecasting)podeser
realizadadaformaimplcitaouexplcita.
Cast implcito
Ocorre quando fazemos converso entre variveis de tipos compatveis, onde no h a necessidade de
utilizaodepalavraschaveparainformaraconversoaocompilador.Ex:
Cast explcito
Utilizamos o cast explcito quando queremos informar ao compilador que no estamos fazendo uma
conversoindesejada,etambmquandoostiposnosocompatveismasaconversonecessria.Abaixo
seguemasformasdefazerocastexplcitoemC++:
(tipo):conversoexplcitadetiposestiloC.consideradaantigaeobsoleta.
static_cast<tipo>(expresso):utilizadoquandoqueremosfazerumcastemtempodecompilao,ou
seja,nohverificaodetiposemtempodeexecuo.Ex:
int sum;
int num = 10;
float pi = 3.14159;
1
Programacomvriaslinhasdeexecuo,chamadasthreads,querodamemparalelo,naticadoprograma.
10
CaptuloIEngenhariadeSoftwareEstruturada
const_cast<tipo>(expressoconstante):utilizadopararetiraraconstnciadeexpresses.Noexemplo
abaixo,podemosdesconsiderarofatoqueconst_ptrumponteiroconstantequandoatribumoseleaum
ponteironormal(nosepreocupe,veremosousodeponteirosmaisadiante):
char * ptr;
const char * const_ptr;
.
.
.
ptr = const_cast <char *> (const_ptr);
reinterpret_cast<tipo>(expresso):oreinterpret_castaformamaispoderosadeconversodetipos.Ele
fora a reinterpretao dos bits da expresso, de forma que os valores reais dos bits de um valor so
utilizados.Devidoaoseupoder,seuusobastanteperigoso,poisfazerumreinterpret_castdeumfloatpara
umint,porexemplo,poderiaresultaremumvalorinteirocompletamentesemsentido.Umexemplodeusodo
reinterpret_castpodeservistoaseguir:
Esteexemplofazcomqueoponteiropointeraponteparaoendereodememria0xB0000000. Seno
utilizssemos o reinterpret_cast, o exemplo acima no compilaria, pois o compilador no considera a
conversodotipounsignedlongparaint*algoquesepossafazerimplicitamente.
dynamic_cast<tipo>(expresso):utilizadoparafazerconversesemtempodeexecuo.Elefazparteda
RTTI(runtimetypeidentificationidentificaodetiposemtempodeexecuo)eservistocomdetalhes
noCaptuloV.
Laos e Condicionais
Elementosessenciaisemlinguagensdeprogramao,asinstruescondicionais(ouinstruesdeseleo,de
acordocomaespecificaodoANSI/ISSOC++)eas instruesdeiterao seroabordadasnestaseo,
bemcomoasinstruesdecontroledefluxo(break,continue,exiteabort).
A instruo if
utilizada para testar expresses e tomar decises. Se a expresso entre parnteses for avaliada como
verdadeiraoudiferentedezero,seublocodeinstruescorrespondenteserexecutado.Possuiumaclusula
opcional,else,queexecutaumblocodeinstruescasoaexpressoentreparntesessejaavaliadacomofalsa.
Podemos ter vrios blocos ifelse aninhados, por exemplo para testar uma varivel sucessivamente, at
encontrarmosumacorrespondncia.Asintaxedainstruoif:
if (expresso)
{
bloco de instrues que
sero executadas caso expresso seja
avaliada como verdadeira;
}
else
{
bloco de instrues que
sero executadas caso expresso seja
11
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
A instruo switch
switch (expresso)
{
case valor1:
instruo1;
[break;]
case valor2:
instruo2;
[break;]
case valor3:
instruo3;
[break;]
.
.
.
default:
instruo_padro;
}
Casoainstruobreaknosejautilizada,oprogramacontinuarexecutandoasinstruesdoprximocase
atquehajaumbreakouqueacabeoblocoswitch.
Umlaowhileexecutaseublocodeinstruesenquantoasuaexpressoforavaliadacomoverdadeira(ou
diferentedezero).Possuiasseguintessintaxes:
while (expresso)
{
instrues;
}
ou
do
{
instrues;
} while (expresso);
Adiferena,quenolaowhilepuro,aexpressoavaliadaantesdeexecutarasinstrues,enquantono
lao dowhile asinstrues soexecutadas eaexpressoavaliadanofinal(portantoasinstrues so
executadaspelomenosumavez).
O lao for
12
CaptuloIEngenhariadeSoftwareEstruturada
Olaoforutilizadoquandodesejamosutilizarumndicenumrico,quesejaincrementado/decrementadoa
cadaiterao.Suasintaxe:
A inicializao executadaantesdecomearemasiteraesdolao.geralmenteondeinicializamosas
variveisdendicequeseroutilizadasnolao.Acadaiterao,aexpresso_de_testeavaliadaeolao
encerrado quando ela se torna falsa. Aps cada execuo do corpo do lao, a expresso_de_iterao
executada.Essaexpresso,geralmente,umincremento/decrementoda(s)varivel(is)dendice.
break:utilizadaparaterminaraexecuodeumlaooudeumblocoswitch.
continue: faz com que a execuo do programa pule para a prxima iterao de um lao, ou seja, as
instruesentrecontinueeofimdocorpodolaonosoexecutadas.
goto label: transfere o fluxo do programa para a instruo seguinte a label. Seu uso extremamente
desaconselhado,poistornaofluxodoprogramabastantedifcildeacompanharedepurar.Sempreexisteuma
formadeescreverumprogramasemgoto.Portantonouseestainstruo.
exit:terminaaexecuodoprograma.Podeserchamadadequalquerfuno,noapenasdafunomain.
abort:terminaimediatamenteaexecuodoprograma,semexecutarasinstruesdeencerramentodetempo
deexecuodoC++(comochamarosdestrutoresdosobjetosglobaisporexemplo).
Ponteiros
AsvariveisponteirosoumdosmaioresrecursosdeC++peloseupoder,mastambmumdosmaiores
causadoresdebugseoterrordealgunsprogramadores.Nestasessoveremosqueosponteirossoumdos
nossosmaioresaliadosetambmveremoscomonocairnassuasarmadilhas.
Apesardeutilizaremespaosdememriadomesmotamanho,poistodososponteirosguardamendereosde
memria,cadaponteiroprecisaserdomesmotipododadoqueeleaponta,ousejaumponteiroparainteiros
deveserdotipo int,enquantoumponteiropara double deveserdotipo double.Paradeclararponteiros,
utilizamosumasterisco,*,apsonomedotipo,daseguinteforma:
int *ponteiro_para_int;
double *ponteiro_para_double;
13
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Utilizando ponteiros
Parautilizarmososponteirosparaapontarparaumavarivel,utilizamosooperadorendereo,&:
ponteiro_para_int = &um_inteiro;
ponteiro_para_double = &um_double;
Paraacessarocontedodasvariveisapontadaspeloponteiro,utilizamosooperador desreferncia,*,que
tambmumasterisco:
Quenosdarcomosada:
O valor de um_inteiro : 10
O valor de um_double : 3.14159
Ooperadordesrefernciafazcomque,emvezdeexibirocontedodavarivelponteiro,queoendereode
um_inteiro, utilize esse contedo como endereo e exiba o contedo deste endereo, que 10.
Complicado?No,muitomaissimplesdoqueseimagina.Vejamosalgunsexemplosdeusodosoperadores
&e*,eoqueaconteceriaemcadacaso:
Exemplo1:
Apesardepassarpelocompilador,esteexemploestariasemanticamenteincorreto,poisoqueseriaexibidoo
endereodeum_inteiroenooseuvalor.
Exemplo2:
Esteexemplocausaerrodecompilaopoisavarivelum_inteiro,apesardeteromesmotamanhodeum
ponteiroeguardarumvalornumrico,nofoideclaradacomoponteiro,enopodeterseucontedoutilizado
paraenderearmemria.
Exemplo3:
Nesteexemplo,estaramosexibindooendereodeponteiro_para_int,enoocontedodoendereo
queeleaponta.Seestivssemosatribuindo&ponteiro_para_intparaumavarivel,comoestavarivel
deveriaserdeclarada?Corretoserespondeu:int**ponteiro_duplo;Poisoendereodeumponteiro
deveserguardadoemumponteiroparaponteiro.
Exemplo4:
14
CaptuloIEngenhariadeSoftwareEstruturada
Estaseriaaformacorretadeutilizaroponteiro,eoqueseriaexibidoseriaovalorguardadonoendereo
guardadonoponteiro.
Comoveremosmaisadiante,almdostiposbsicos,podemosutilizarponteirosparatiposcompostos,objetos
efunes.
Atagora,todaamemriaquensutilizamoseraalocadaatravsdadeclaraodevariveis,oquesignifica
queestvamosinformandoaoC++oquantodememriaqueonossoprogramairiautilizar.Comovimos
anteriormente, a memria do nosso programa est dividida em trs classes de armazenamento: o
armazenamentoautomtico(paravariveisdeclaradaslocalmente),oarmazenamentoesttico(paravariveis
declaradascomstaticeparaasvariveisglobais)eoarmazenamentolivre(paraasvariveisdeclaradasem
tempodeexecuo).Portanto,podemosalocareliberarmemriadareadearmazenamentolivre,emtempo
deexecuo,oquenospermiteumamaioreficincianogerenciamentodememria.Istofeitoatravsdos
operadoresnewedelete.
Ooperadornewretornaumponteiroparaotipoespecificado,deformaque,sequisermoscriaruminteiroem
tempodeexecuo,devemosprocederdaseguinteforma:
int *ponteiro_para_int;
ponteiro_para_int = new int;
Agoravocentendeousodeponteiros,poisnofezmuitosentidooseuusocomonosexemplosdaseo
utilizandoponteiros,certo?
Asvariveisdareadearmazenamentoautomticosodesalocadaslogoqueoprogramasaidoseuescopo,
automaticamente (da o nome armazenamento automtico). Isto no ocorre com as variveis da rea de
armazenamento livre. Embora possam estar sendo referenciadas por ponteiros declarados localmente (e
portanto, localizados na rea de armazenamento automtico), todas as variveis criadas dinamicamente
continuam aexistirdurante todaaexecuo doprograma, ouatquesejam desalocadas explicitamente.
Vejamosummauusodealocaodinmica:
15
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Adiferenaentreesteexemploeoanterioraltimainstruodocorpodolao:delete pointer;Esta
instruodesalocaamemriaalocadapelonew.Portanto,desumaimportnciaadesalocaodasvariveis
quenoseromaisutilizadas,sobpenadecausarumestourodememrianoprograma.Umaobservaoque
deve serfeitaaqui: quandoutilizamos o new,caso elenoconsigaalocar amemriacorrespondente,
retornar um ponteiro nulo (que possui o valor zero). Portanto, sempre que alocarmos memria
dinamicamente,devemosverificarseistorealmentefoifeitocomsucesso,comparandooponteirocoma
constanteNULL,paraqueoprogramanoencerreabruptamentedevidoaerrosemtempodeexecuo.
PodemosutilizarponteirosparaapontarparaqualquertipodedadosemC++,inclusivearrays,estruturas,
uniesetiposenumerados(eobjetos,comoveremosposteriormente).Abaixosegueumexemplodecomo
utilizarponteiroscomestruturas(ousocomuniesanlogo):
struct TBall
{
int x,
int y,
int radius,
TColor color
} ball_1, *pointer;
pointer = &ball_1;
(*pointer).x = 10;
pointer->y = 20;
Portanto, para acessar um membro da estrutura, basta utilizar (*pointer) pois isto desreferencia o
ponteiro.Podemosutilizartambmooperadorseta, ->.Comooperadorseta,podemosutilizaroponteiro
diretamente,semprecisardesreferencilocom*.
Ponteiros e arrays
EmC++,ponteirosearrayssobastantesemelhantes.Podemosutilizarponteiroscomosefossemarrays(com
ooperadorcolchetes,[])eonomedoarraycomoumponteiroparaasuaprimeiraposio.Abaixosegueum
exemplodecomoutilizarponteiroscomoarrays:
int array[5];
int *pointer;
array[0] = 10;
array[1] = 20;
array[2] = 30;
array[3] = 40;
array[4] = 50;
pointer = &array[0];
16
CaptuloIEngenhariadeSoftwareEstruturada
Podemoscriararraysemtempodeexecuocomooperadornewemconjuntocom[]:
int *pointer;
pointer = new int[10];
pointer[0] = 10;
ComoC++permiteutilizarmosponteiroscomooperadorcolchetes,[],pointersecomportarcomoum
array.Paradesalocaramemriaalocadacomnew[],utilizamosdelete[]:
delete[] pointer;
Aritmtica de ponteiros
Comosabemos,osponteirossovariveisqueguardamendereosdememria.Porseremvaloresinteiros,
podemos utilizar operaes aritmticas com ponteiros. A diferena que, se executarmos a instruo:
um_inteiro++;avarivelum_inteiroseracrescidade1.Seexecutarmos:pointer++;avarivelpointerser
acrescidadeumnmeroigualaotamanhodotipodepointer,ouseja,sepointerforumponteiroparaint,seu
valorseracrescidode4(uminteirotemgeralmente4bytes),deformaque,sepointerestiverapontandopara
umaseqnciadeinteiros,pointer++farcomqueeleaponteparaoprximoelemento.Parailustrarmelhora
aritmticacomponteiros,segueumexemplo:
Nesteexemplo,emvezdeacessarmososelementosdoarrayatravsdooperadorcolchetes,[],utilizamosum
ponteiroparapercorrlo.Comovimosanteriormente,arrayseponteirossosemelhantes,deformaqueesta
aritmticatambmvaleparaarrays:*(array+n)equivalenteaarray[n].
Ponteiros e const
Alm de podermos declarar ponteiros para variveis, C++ nos permite declarar ponteiros para valores
constantes:
Istonosignificaqueoponteirospoderapontarparaconstantes.Narealidadeoqueestamosfazendo
informandoaocompiladorqueeledevetratarovalorparaoqualoponteiroapontacomoumaconstante,e
qualquer tentativa de tratlo de forma diferente causar erro de compilao. A importncia de utilizar
ponteirosdestaforma,nosprevenirmosdeerrosqueocorreriamseovalorfosseinadvertidamentealterado.
17
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Outromotivoquesponteirosparaconstantespodemapontarparaconstantes,osponteirosnormaisno
(istoumtantoquantobvio).
Apalavrachave const tambmpodeserutilizadaparadeclararponteirosconstantes(noteadiferenade
ponteirosparaconstantes).Comoeradeseesperarponteirosconstantesspoderoapontarparaumendereo
dememriaconstante,ouseja,nopodemalteraroendereocontidonele.Exemplo:
int um_inteiro;
int *const pointer = &um_inteiro;
Portanto,comovocjdevedesconfiar,tambmpodemoscriarponteirosconstantesparaconstantes,oque
significaquenopoderemosalteraroendereocontidoneleequeovalorcontidonesteendereosertratado
comoconstante:
int um_inteiro;
const int *const pointer = &um_inteiro;
Funes
Comovimosnoinciodocaptulo,asfunessoabasedaengenhariadesoftwareestruturada.Entovamos
aelas!
Definindo funes
Paradefinirumafuno,utilizamosaseguinteestrutura:
tipo nome(argumentos...)
{
instrues;
return expresso_de_retorno;
}
Onde:
tipo:otipoderetornodafuno.
nome:onomedafuno.
argumentos: lista de zero ou mais parmetros que devem ser passados funo quando a mesma
chamada.
instrues:conjuntodeinstruesqueseroexecutadasquandoafunoforchamada.
expresso_de_retorno:expressoretornadaparaopontoondeafunofoichamada.Deveserdo
mesmotipodetipo.
Abaixosegueumexemplodeumadefiniodefuno:
Claroqueasfunesquenscriamossogeralmenteumpoucomaiscomplexas,masesteexemploilustra
bemoselementosdadefiniodeumafuno.
Em C++, alm de definirmos umafuno (com todos os seus elementos), devemos tambm declarar as
funesquedefinimos.Estadeclaraochamadadeprottipodeumafuno.Oprottipodeumafuno
nadamaisdoqueaprimeiralinhadadefiniodafunoseguidadeumpontoevrgula.Ex:
18
CaptuloIEngenhariadeSoftwareEstruturada
Ocdigoacimademonstraoprottipodafunoadd,definidanoexemploanterior.
Paraestruturarmelhorocdigo,criamosumarquivocomextensocppcomasdefiniesdasfuneseum
arquivocomextenso.hcomosprottiposdasfunes.
Podemospassarqualquertipodedadoscomoargumento(ouparmetro)paraumafuno.Abaixoveremos
algumaspeculiaridadesdostiposdedadosmaiscomplexos,ecomoretornarestestipos.
Funes e arrays
Parapassarumarrayparaumafuno,bastaadicionar[]aonomedoargumento,ex:
bastanteimportanteressaltaroqueestacontecendoaqui.AolembrarmosqueC++trataonomedearrays
comoponteirosconstantes,podemosperceberqueoqueestamospassandocomoargumentonoumacpia
dequalquerelementodoarray,massimumponteiroparaoarrayoriginal.Comopodemosutilizarponteiros
comoarrays(comooperador[]),aprimeiravista,ocdigoacimapodenodemonstrarorealmenteest
acontecendo.Portanto,sealterssemosqualquerelementodoarray,estaramosalterandonoarrayoriginal.
Para prevenirmos alteraes inadvertidas, devemos declarar oparmetro doarray comoconstante, como
veremosabaixo:
Destaforma,garantimosqueapassagemdeparmetrosporrefernciaqueestimplcitanoimpliqueemum
errogravenonossoprograma.
OC++nopermiteatribuirumarrayinteiroaoutro,nemretornarumarrayinteirodeumafuno.Portanto,
pararetornarumarraydeumafuno(eeventualmenteatribuiristoaoutro),devemosusarponteiros.Como
existeumasemelhanaentreponteirosearrays,esteprocessobastantesimples.Vejamosumexemplo:
19
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
{
int *retorno = new int[num_elementos];
Devemosobservarosseguintesaspectosnotrechodecdigoacima:
Otipoderetornodafunonarealidadeumponteiro,comojfoiexplicadoantes.Portanto,o
resultadodestafunospodeseratribudoaponteiros,enoaarrays.
A varivel de retorno no foi declarada como um array normal como: int
array[num_elementos] pois, se fosse declarada desta forma, seria alocada na rea de
armazenamentoautomtico,sendodesalocadaaofinaldoseuescopo,ouseja,nofimdafuno.
Ento,quandotentssemosutilizaroarrayderetornodafunoestaramostrabalhandocomuma
readememriadesalocada,quepoderiaconterqualquercoisa,oupior,tersidoalocadaparaoutra
varivel.
Notequealocamosmemriadentrodestafunoenodesalocamos.Portanto,tarefadocdigoque
chamouafunodesalocarestamemriacomooperadordelete[],quandoeladeixardeserutilizada.
Funes e estruturas
EmC++,asestruturassopassadasparaasfunescomovalor,deformaquepassarumaestruturaparauma
funoomesmoquepassarumavarivelsimples.Exemplo:
struct structure
{
int um_inteiro;
char um_char;
};
Napassagemdeparmetrosporvalor,oqueacontecequeaestruturapassadacopiadaparaumavarivel
local,noarmazenamentoautomtico.Portanto,parapassarestruturasgrandespodemosoptarporpassarum
ponteiroparaaestrutura,evitandoassimooverhead2dacpia.
Omesmoseaplicaaoretornarestruturasdeumafuno,aestruturatambmpassadaporvalor.Exemplo:
structure get_structure()
{
structure estrutura;
estrutura.um_inteiro = 0;
estrutura.um_char = A;
return estrutura;
}
2
Tempogastocomexecuodecdigoquenofoicriadopeloprogramador,equeportanto,nofazpartedo
programadiretamente.
20
CaptuloIEngenhariadeSoftwareEstruturada
Comoaestruturapassadaporvalor,noprecisamosnospreocuparcomseuescopo.Narealidade,avarivel
estrutura perdeoescopoaofimdafuno,mascomooqueretornadoumacpiadamesma,no
precisamosnospreocuparcomisto.
Comovimosanteriormente,podemosutilizarponteirosparaqualquertipodedados.Nestaseoveremosque
tambmpodemosutilizarponteirosparafunes.Comoasfunessodadoscompiladosarmazenadosna
memria,nadanosimpedequetenhamosumponteiroparaestesdados.Umponteiroparafunoapontapara
posiodememriaparaaqualoprogramatransferidoquandoafunochamada.Utilizamosponteiros
parafunesparapassarestasfunescomoargumentoparaoutrasfunes.Seoprottipodeumafuno:
Umponteiroparaestafunopoderiaserdeclaradodaseguinteforma:
Damesmaformaqueonomedeumarrayumponteiroconstanteparaoarray,onomedeumafunoum
ponteiroconstanteparaafuno,deformaquepodemosinicializaronossoponteirodaseguinteforma:
ponteiro_para_funo = funao;
Parapassarmosumafunocomoparmetroparaoutra,passamosafunocomoponteiro:
Como podemos observar, funo2 recebe uma funo como parmetro e chama esta funo com o
argumento13723.
Funes in-line
Quandofazemosumachamaaumafuno,ofluxodoprogramadesviadoparaoendereodafuno,seus
argumentossocolocadosnapilha,entreoutrascoisas.Istogeraumoverheadnaexecuodeumprograma.
Parasituaescrticas,oufunesbastantepequenas(comumaouduasinstrues),C++nospermitecriar
funesinline.Nolugardaschamadasaestasfunes,ocompiladorcolocatodoocdigodafuno,de
formaquenenhumdesvionecessrio.Adefiniodeumafunoinlinefeitacomapalavrachaveinline:
Destaforma,todavezquefizermosumachamadafunodobro,ocdigo:2*numsercolocadoemseu
lugar.
21
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
C+ tambm nos permite utilizar os argumentos de funo de forma bastante eficiente. Podemos definir
argumentospadroouumnmerovariveldeargumentosparaumafuno,comoveremosaseguir.
Argumentos padro
Definindoargumentospadroparaumafuno,estamosespecificandoumvalorqueserutilizadocasono
seja fornecido nenhum valor para o argumento. Para definir um argumento padro para uma funo,
utilizamosoigual,=,seguidopelovalor_padro,nadefiniodoprottipodafuno:
result = sum(10);
Nocdigoacima,comonum2foideclaradocomvalorpadroiguala1,semprequefizermosumachamadaa
sumsemosegundoargumento,ovalor1serutilizadonoseulugar.Portanto,quandodefinimosumvalor
padroparaumargumento,devemosomitiresteargumentoparautilizarseuvalorpadro.Istoquerdizerque
osargumentospadrodevemserosltimosargumentosdafuno,pois,casoistonoocorra,ocompilador
serincapazdeidentificarqualdosargumentosestfaltando.
Argumentos variveis
Almdedefinirargumentospadro,C++disponibilizaumconjuntodemacrosparaquepossamosdefinir
umafunocomumnmerodeargumentosvarivel.Estasmacrosso:
va_list:obtmalistadeargumentospassadosparaafuno
va_start(va_list list, int num_elementos):inicializaalista
va_arg(va_list list, tipo):retornaumargumentodalista
va_end(va_list list):finalizaousodalistadeargumentos
Parautilizarmosasmacros,devemosincluiroarquivodecabealho cstdarg.Abaixosegueumexemplo
quemostracomocriarumafunocomumnmerodeargumentosvarivel:
int sum(int...);
int main ()
{
cout a soma de 1, 2 e 3 : << sum(3, 1, 2, 3) << endl;
return 0;
}
22
CaptuloIEngenhariadeSoftwareEstruturada
resultado += numero;
}
va_end(lista);
return resultado;
}
Nesteexemplo,afunosumrecebeumargumentoobrigatrio,queaquantidadedeargumentosvariveis
que estamos passando, seguido de vrios argumentos. Ento, utiliza as macros para percorrer a lista de
argumentosesomlos.
Sobrecarga de funes
svezes,desejamoscriarumafunoquepossaserchamadacomdiferentestiposdeargumento.Istonos
permitepersonalizarocdigoetornlomuitomaisfcildetrabalhar.C++permitequesobrecarreguemos
funesparaqueestasaceitemargumentosdetiposenmerosdiferentes.Paraisto,bastaapenasdefiniras
funestantasvezesquantasforemnecessrias.Notequeaassinatura,listadeargumentosdafuno,deveser
diferente, ouseja:otipoouaquantidade(noapenas onome)dosargumentos deveserdiferentes,nas
diferentesversesdeumafunosobrecarregada.Abaixosegueumexemplodesobrecargadefuno:
int main()
{
int num1= 10, num2 = 15, num3 = 20;
char const *str1 = "World!";
char str2[20] = "great ";
char str3[20] = "Hello ";
cout << "--- Funcao sum com inteiros ---" << endl;
cout << "soma total: " << sum(num3, sum(num2, num1)) << endl;
cout << "num1: " << num1 << endl;
cout << "num2: " << num2 << endl;
cout << "num3: " << num3 << endl << endl;
cout << "--- Funcao sum com strings ---" << endl;
cout << "Strings: " << sum(str3, sum(str2, str1)) << endl;
cout << "str1: " << str1 << endl;
cout << "str2: " << str2 << endl;
cout << "str3: " << str3 << endl;
cin.get();
return 0;
}
23
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Nocdigoacima,afunosumpodeserutilizadadamesmaformacominteirosestrings.Foiutilizado
const char*str2,comosegundoargumento,paragarantirqueesteargumentonoseriamodificadono
corpodafuno.
24
CaptuloIEngenhariadeSoftwareEstruturada
Comoprticadestecaptulo,iremosprojetaronossojogoutilizandofunes.Iremoscriarfunespara:
Apagaratela
Desenhareapagarumblocoemumaposiodatela
Desenhareapagarabarraemumaposiodatela
Desenhareapagarabolaemumaposiodatela
Moverabolaetestaracolisocomosoutrosobjetos
Moverabarradeacordocomentradadoteclado
Abaixoseguemasseqnciasdecaracteresdeescapequemodificamoestadodatela,seenviadasparacout
(ESCsignificaocaracteredeescape,cujocdigoascii27):
Funo Seqnciadecaracteres
Normal ESC[0m
Bold ESC[1m
Blink (piscando) ESC[5m
Reverso (cores do texto e fundo trocadas) ESC[7m
Mover para a posio 0,0 ESC[f
Mover para a posio x,y ESC[f ESC[yB ESC[xC
Apagaratela ESC[fESC[2J
Mudaracorparaatr,fg,bg(atr=0(normal)ou ESC[atr;fg;bgm
atr=1(highlight),fg=texto,bg=fundo)
25
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
26
Captulo II
Comocrescimentodacomplexidadedosprogramas,tornousedegrandevaliaadecomposiodosmesmos
em unidades menores. A decomposio de um programa em mdulos permite diminuir o tempo de
programaoaoseprogramarosmdulosemparalelo,divideoproblemaaserresolvidoempartesmenorese
mais fceis de serem implementadas e permite compilar e testar estas partes separadamente. Mas a
modularizao no traz s vantagens. Uma modularizao mal feita pode acarretar em problemas com
reusabilidade, extensibilidade, compatibilidade, etc. Os fatores que influenciam na modularizao so: a
coeso, interdependncia das funes e estruturas internas de um mdulo; e o acoplamento, nvel de
dependnciaentreosmdulos.Portanto,paramodularizarumprogramacorretamente,devemos:
Maximizaracoeso:asfuneseestruturasdedadosqueimplementamumafuncionalidade(ou
conjuntodefuncionalidadesrelacionadas)doprogramadevemestarnomesmomdulo.
Minimizaroacoplamento:osmdulosdevemfuncionarosmaisindependentespossveisdosoutros
mdulos,paraqueaomodificarmosummdulonosejanecessriomodificarosdemais.
Information Hidding
Para garantir um fraco acoplamento entre os mdulos, devemos fazer com que um mdulo conhea
somenteonecessriosobreofuncionamentointernodosmdulosqueeleutiliza.Portanto,devemosdefinir
uma interfaceparacomunicao entreosmdulos,deformaquenosejavisvelasuaestruturainterna,
apenasasuainterface.
Ento,depoisdedefinidososconceitosbsicosdaengenhariadesoftwarebaseadaemobjetos,podemos
formularumadefiniodemdulomaisconcretaequeserusadadeagoraemdiante:
C++permiteadivisodenossosprogramasemdiversosarquivos,deformaapodermosterarquivospara
cada mdulodenossoprograma. Asinterfaces dosmdulossodefinidasem arquivoscomextenso .h
(arquivosdecabealhodeC++)enquantoaimplementaoestnosarquivoscomextenso.cpp.Quandoum
mdulonecessitarutilizaroutro,deveincluiroarquivodecabealhocorrespondenteeainterfacedomdulo
aserutilizadoficardisponvel.
Definindo interfaces
3
Informationhiddingumconceitodeengenhariadesoftwarequeconsisteemencapsularosdadosdeum
mdulodeformaqueestesssejamacessveisatravsdainterfacedomdulo.
28
CaptuloIIEngenhariadeSoftwareBaseadaemObjetos
Asinterfacesdosmdulossocriadasemarquivos.h.C++permiteacriaodeespaosdenomesseparados
paracadamdulo,paraquenosecorraoriscodeexistirconflitoentrenomesdedadosoufunesiguaisem
mdulosdiferentes.Istofeitoutilizandoseapalavrachavenamespace.
Comovimosanteriormente,podemosutilizaraspalavraschaveexternestaticparadefiniraligao(externa
ouinterna)dosdados.Veremosestesconceitosnaprticanaprximaseo.
Abaixosegueummodelobsicodosarquivosdeummdulochamadomodulo1,comexplicaessobresuas
partes:
//-----------------------------------------------------------------
/* Arquivo modulo1.h */
//-----------------------------------------------------------------
/* Arquivo modulo1.cpp */
// definicoes privadas
static int funcao1(int num1, int num2);
static char *str1 = "Modulo 1 - variavel privada";
// variavel publica
char *str2 = "Modulo 1 - variavel publica";
// funcoes publicas
int funcao2(int num1, int num2)
{
return num1*num2;
}
void printResults()
{
cout <<"Usando funcao1 do modulo 1: "<<funcao1(1, 2)<<endl;
29
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
// funcao privada
static int funcao1(int num1, int num2)
{
return num1+num2;
}
} /* fim do arquivo modulo1.cpp */
//-----------------------------------------------------------------
Construo:deveserpossvelalocareinicializarnovasinstnciasdoADT.
Atribuio:devemospodercopiarosdadosdeumainstnciaparaoutra.
Comparao:deveserpossvelcompararduasinstnciasdeumADT(atenosdiferenasentre
identidadeeigualdade)
Manipulaodosdados:devemospodermanipularosdadosdeumADTsemsepreocuparcoma
formadearmazenamentointerno,deformaaencapsularoADT.
Destruio:devemosterapossibilidadedeliberaramemriaalocadaporumADT,quandono
formosmaisutilizlo.
AodefinirmosumADTtendoemmenteestasresponsabilidadesestaremosimplicitamenteaplicandotodosos
conceitosdeengenhariadesoftwarequeaprendemosatagora.
Comovimos,C++umalinguagemfortementetipada,oquenosimpedede,aodefinirmosumafunoque
manipulainteiros,utilizalacomnmerosdepontoflutuante,porexemplo.Sedesejarmosumafunoque
tenhaomesmocomportamento(asmesmasinstrues)paraambososcasos,podemossobrecarregaresta
funo,masistofeririaoconceitodereusabilidadedecdigo,poisteramoscdigosidnticosreplicados.
MasoC++ofereceumaalternativaparaisto:podemoscriarmodelosdefuno,queindependamdotipode
dados, e utilizar este modelo para ambos os tipos. Para criar modelos de funo (function templates),
utilizaremosaspalavrastemplateetypename:
int main()
{
int num1 = 10;
30
CaptuloIIEngenhariadeSoftwareBaseadaemObjetos
add(num1);
add(num2);
add(num3);
cin.get();
return 0;
}
Comopodemosperceber,ocompiladorseencarregoudegerarafunoparacadatipodedado.Masoque
ocorreriaseutilizssemosumtipoparaoqualafunonoadequada?Afunoaddfuncionamuitobem
paratiposnumricos,masnoseriaadequadaparastringsporexemplo.Podemos,entodefinirumafuno
addparaotipostringqueexibaumamensagemdeerro,informandoqueaddnoadequadaparastrings.Isto
feitocriandoespecializaesdafunotemplate.Paracriarumaespecializaoparaumdeterminadotipo,
utilizamostemplate<>,edeclaramosafunocomotipodesejado:
template <>
void add (char *str)
{
cout << No possvel adicionar um string << str << endl;
}
31
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
screen.cpp responsvelpelasrotinasdedesenhoemanipulaodeimagensnatela.
game.cpp responsvelpelocontroleprincipaldojogo,pontuaoeentradadoteclado.
sprites.cpp responsvelpelocontroleemovimentaodoselementosdojogo(blocos,bolaebarra).
noid.cpp Possuiafunomainepossveisfunesauxiliares.
Devemos definir as interfaces de cada mdulo antes de comear a implementlos. Faa diagramas
representandoasrelaesentreosmdulosparaajudlo.Osmdulosdevemserimplementadosseguindoos
princpiosdeumADT.
32
Captulo III
Classes em C++
Vamosiniciaronossoaprendizadopartindodeumaestrutura.Damesmaformaqueadicionamosvariveis,
podemosadicionarfunesaumaestrutura:
struct TBall
{
int x, y;
TColor color;
int radius;
Portanto,aestruturaTBallagorapossuiumafunomembro.Istosignificaqueafunopertenceestrutura
espodeserchamadaapartirdela.Tambmpodemosobservarqueosmembrosdaestruturasovisveis
dentrodafunomembro.Paratransformarestaestruturaemumaclasse,asnicascoisasquedevemosfazer
so:substituirstructporclasseadicionarapalavrachavepublic:paraindicarquepodemosacessar
osmembrosdaclasse:
class TBall
{
public:
int x, y;
TColor color;
int radius;
Comestesexemplospodemosperceberumadasdiferenasentreclasseseestruturas:nasestruturas,todosos
membrossopblicos,enquantonasclassespodemosdeterminaravisibilidadedosmembrosatravsdos
seguintesmodificadores:
34
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
public:tornaosmembrosdaclassevisveisforadaclasse
protected:osmembrosdaclassessovisveisdentrodaprpriaclasseenasclassesderivadas
(veremoscomocriarclassesderivadas,ousubclasses,noprximocaptulo).
private: osmembrosdaclassessovisveisdentrodaprpriaclasse.
Portanto,umavezvistocomodefinirumaclasse,eisumexemplodaclasseTBallcomtodososrequisitos
deumADT:
class TBall
{
private: // os atributos da classe so todos privados
// lembre-se do conceito de information hidding
int x, y;
TColor color;
int radius;
35
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
int getX()
{
return x;
}
int getY()
{
return y;
}
TColor getColor()
{
return color;
}
int getRadius()
{
return radius;
}
void setColor(TColor c)
{
color = c;
}
void setRadius(int r)
{
radius = r;
}
};
Portanto,aestanossaprimeiraclasse,seguindotodososrequisitosdaengenhariadesoftware.importante
salientarqueumaclassepodecontertantosconstrutoresquantosforemnecessrios,masdevepossuirum
nicodestrutor.Comoodestrutorchamadopelaestruturainternadoprograma,quandoumobjetosaido
escopoouquandoutilizamosooperadordelete,umdestrutornopossuiparmetros.
Apesar de poder criar classes da forma como criamos anteriormente, C++ nos d a possibilidade de
separarmosadeclaraodaclasse(arquivos.h)desuaimplementao(arquivos.cpp).Destaforma,podemos
utilizaraclasseemdiversosoutrosarquivos,bastandoparaistoincluiroarquivodecabealhoquecontma
definiodaclasse.Narealidade,estaaformacorretadeimplementao,poisaodefinirmosumaclasse
comocorpodosmtodosnadeclarao,ocompiladortrataistocomosefosseumadeclaraoimplcitade
mtodosinline,oquenodesejadoparatodososmtodos.Abaixosegueumexemploresumidodecomo
dividirumaclasseemarquivosdecabealhoeimplementao:
/* Arquivo TBall.h */
36
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
#ifndef TBALL_H
#define TBALL_H
class TBall
{
private:
int x, y;
TColor color;
int radius;
public:
void move(int x_step, int y_step); // declarao dos mtodos
.
.
.
};
#endif
/* fim de TBall.h */
/*Arquivo TBall.cpp*/
Comoumaclassedefineumescopo,aimplementaodosmtodosdeumaclassedevevirprecedidadonome
daclasseseguidopelooperadordeescopo::.
Modificadores de mtodos
Almdaformanormaldedeclararmtodos,C++ofereceumconjuntodemodificadoresdemtodos(alguns
jvistoscomfunes)quealteramaformacomoestessoutilizados.
Mtodos in-line
Comovimos anteriormente, os mtodos cuja implementao est dentro dadefinio da classe so,por
padro,inline.Umaoutraformadecriarmtodosinlineutilizandoapalavraclaveinline,comoveremosa
seguir:
Adeclaraodomtodonadefiniodaclassecontinuasendofeitadamesmaforma.
Mtodos constantes
37
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Como vimos anteriormente, podemos declarar variveis externas como estticas para tornar sua ligao
interna e declarar variveis automticas comoestticas para mudar asua classede armazenamento para
esttica.Emumaclassepodemosutilizaromodificadorstaticdeduasformas:
Usandostaticcomumatributo,tornamosesteatributocompartilhadocomtodososobjetosdaclasse,
ouseja,todososobjetosdaclassecompartilhamamesmaposiodememriaparaesteatributo.
Usandostaticcomummtodo,estesetornamtododaclasse,enodoobjeto,deformaqueno
precisamosinstanciarumobjetodaclasseparachamaromtodo.Comoosmtodosestticosno
fazempartedenenhumobjetodememria,elesspodemacessarosatributosestticosdaclasse.
Parachamarummtodoesttico,procedemosdaseguinteforma:
class TBall
{
public:
static string getInfo();
.
.
.
};
int main ()
{
cout << TBall::getInfo() << endl;
return 0;
}
O ponteiro this
TodaclasseemC++possuiumponteiroespecialchamadothis,queapontaparaainstanciaatualdoobjeto.
Porexemplo,secriarmosummtodoquenecessiteretornaroprprioobjeto,podemosutilizarthisparaisto.
Ex:
class TBall
{
TBall & compare(const TBall &ball);
.
.
38
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
.
};
int main ()
{
TBall ball1(10, 20, clWhite, 30);
TBall ball2(30, 100, clBlack, 10);
return 0;
}
Asadadoprogramaser:
Podemosperceber,nesteexemplo,quepassamoseretornamosoobjetoTBallporreferncia.Porqueisto
feito?VocdevelembrarqueoC++,aopassarumestruturaparaumafuno,passaaporvalor,fazendouma
cpiadaestruturanareadearmazenamentoautomtico.Comobjetosaconteceomesmo.Paraevitareste
overhead da cpia, os parmetros so passados por referncia, e, quando no sero alterados dentro do
mtodo,sopassadoscomorefernciaconstante.
Domesmomodoquesobrecarregamosfunes,C++nospermitesobrecarregarmtodoseconstrutores.Para
isto, redefinimos o mtodo ou construtor com uma assinatura (lista de argumentos) diferente. Ento o
compiladorseencarregadeverificarqualdasformassobrecarregadasdomtodoouconstrutorserutilizada,
combasenasualistadeargumentos.
Construtores de cpia
Osobjetos,comoasestruturas,sopassadosdeeparafunes/mtodosporvalor.Istoquedizerque,ao
retornarmosumobjeto,porexemplo,umacpiadoobjetopassadaemseulugar.Istotambmocorrequando
fazemosumaatribuio,comooperadorigual,=(veremoscomocorrigiresteproblemacomasobrecargado
operadorigual,=,maisafrente,nestecaptulo).Entooqueaconteceseoobjetotivermembrosqueso
ponteiros?Exatamente!Apesardoponteirosercopiado,elecontinuaapontandoparaamesmaposiode
memriaqueoponteirodoobjetoantigo.Portanto,oobjetoantigoeonovoteroumamesma reade
memriacompartilhada.
Para resolveresteproblema, C++oferece os construtores decpia. Narealidade, todaclassepossuium
construtordecpiapadro,quesimplesmentecopiaosvalores dosmembrosdeumobjetoparaooutro.
Quandodefinimosumaclassequetemmembrosquesoponteiros,devemoscriaronossoprprioconstrutor
decpia.Paraisto,bastacriarmosumconstrutorquerecebaumarefernciaconstanteparaumobjetoda
mesma classe. Neste construtor, podemos reinicializar quaisquer ponteiros ou outros dados, conforme a
necessidade,paracriarmosanovacpiadoobjeto.Vejamosumexemplo:
39
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
class TPlayer
{
private:
char *name;
int score;
public:
TPlayer(char *str, int scr);
Tplayer(const TPlayer & player);
.
.
.
};
Usarconstrutoresdecpiadevesetornarumhbitodaquiparafrente,principalmentesetivermosobjetosque
armazenemponteiros.
class TPlayer
{
private:
char *name;
int score;
public:
friend void display(const Tplayer & player);
.
.
.
};
40
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
Acriaodeummtodofriendanlogadeumafunofriend,anicadiferenaqueestamosutilizando
ummtodoenoumafuno(claro!).Vejamosumexemplo:
class TPlayer;
class TScreen
{
public:
void display(const TPlayer & player);
};
class TPlayer
{
private:
char *name;
int score;
public:
friend void TScreen::display(const TPlayer & player);
.
.
.
};
NotequetivemosquedeclararaclasseTPlayer (vejaaprimeiralinhadoexemplo)antesdeutilizlano
mtododisplaydeTScreen.NopodamossimplesmentetercolocadoaclasseTPlayerantespoisela
declaraomtododisplaydeTScreencomofriend,eocompiladorreclamariaqueaindanoviua
classeTScreen.
Aodeclararumaclassecomofrienddeoutraclasse,aprimeiratemacessoatodososmembrosdasegunda
(comojeradeseesperar).Portanto,todososseusmtodostornamsefrienddasegundaclasse.Exemplo:
class TPlayer
{
private:
char *name;
int score;
41
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
class TScreen
{
public:
void display(const TPlayer & player);
};
Alm de converses entre tipos bsicos, C++ nos permite definir converses entre os nossos objetos,
tornandoosomaisparecidospossvelcomostiposbsicosdalinguagem.
Paraconverterumtipodedadosparaumobjeto,devemoscriarumconstrutordeconverso.Esteconstrutor
recebe como argumento o tipo de dados e cria um novo objeto, atribuindo este tipo ao membro
correspondentedoobjetocriado.Porexemplo,sequisssemosatribuiruminteiroaumobjetodotipoTBall
eesteinteirorepresentasseoraiodabola,deveramoscriarumconstrutordaseguinteforma:
TBall::TBall(int r)
{
x = 0;
y = 0;
radius = r;
color = clBlack;
}
Ento,ocdigoabaixofuncionariacorretamente:
TBall ball1;
ball1 = 10;
Paraconverterumobjetoparaumtipodedado,utilizamosmtodosespeciais.Porexemplo,paraconverter
umTBallparaumint(querepresentariaoraiodabola),declaramosummtododenome:
operator int();
Eisumexemplo:
class TBall
{
42
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
private:
int x, y;
TColor color;
int radius;
public:
operator int() const;
.
.
.
};
Assim,ocdigoabaixotambmfuncionarcorretamente:
Sobrecarga de operadores
UmdosrecursosmaisinteressantesepotentesdeC++(eumadasdiferenasentreC++eoutraslinguagens
POOcomoJava,porexemplo)apossibilidadedesobrecarregaroperadoresparamanipularosobjetosdas
classesquecriamos.Aofazersobrecargadeoperadores,devemosseguirasseguintesrestries:
nopodemossobrecarregarosoperadores: sizeof,.,::,.*,?:,type_id,const_cast,dynamic_cast,
reinterpret_castestatic_cast;
os operadores sobrecarregados devem ser usados com pelo menos um operando do tipo
sobrecarregado;
nopossvelcriaroperadorescompletamentenovosnemmudarumoperadordebinrioparaunrio
eviceversa.
Apesardisto,podemossobrecarregartodososdemaisoperadores,inclusivenew,delete,[],+=,<<e>>.
Asobrecargadeoperadoressemelhantesobrecargademtodos,adiferenaqueutilizamosapalavra
chave operator para indicar que estamos sobrecarregando um operador. Nas sees seguintes, veremos
algumaspeculiaridadesdasobrecargadeoperadoresquenecessitamdeumaatenoamais.
Parasobrecarregarumoperadorunrio,devemoscriarummtodonaclassecomaseguintesintaxe:
tipo operatorop()
{
Ondetipo,otipoderetornodooperador,quenestecasoonomedaclasseeopooperadoremsi,como+
+ou.
Portanto,parasobrecarregarooperador++daclasseTBallqueincrementaoraiodabola,procedemosda
seguinteforma:
43
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
class TBall
{
private:
int x, y;
TColor color;
int radius;
public:
TBall & operator++();
.
.
.
};
Devemosobservarqueestecdigossobrecarregaooperador++prfixado.Parasobrecarregarooperador
psfixado,utilizamos:
TBall operator++(int);
Ondeoargumentointdiferenciaosoperadores.
Parasobrecarregaroperadoresbinrios,devemospassarcomoargumentodooperadorumobjetodotipodo
segundooperando(istopermitequeutilizemosesteoperadorcomobjetosdetiposdiferentes,porexemplo).A
sintaxe:
class TBall
{
private:
int x, y;
TColor color;
int radius;
public:
TBall(const TBall &ball);
TBall operator+(const TBall &ball);
.
.
.
};
44
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
Notequecriamosumnovoobjetodentrodocorpodooperadoreretornamosesteobjeto(narealidadeuma
cpiadesteobjeto).
Masoqueaconteceriasedesejssemosfazercoisasdotipo:ball = ball + 2ouball = 2 + ball?
Comonasegundaexpresso,ooperandonoumobjeto,devemosdefinirumafuno friend quereceba
ambososoperandos.Vejamosumexemplo:
class TBall
{
private:
int x, y;
TColor color;
int radius;
public:
TBall(int x1, int y1, TColor c, int r);
TBall(int r);
friend TBall operator+(const TBall &ball1, const TBall &ball2);
.
.
.
};
TBall::TBall(int r)
{
x = 0;
y = 0;
radius = r;
color = clBlack;
}
DevemosnotarquecriamosumconstrutordeconversodeintparaTBall,demodoestasoluoatendea
todasasexpressesvistasanteriormente.Esteumdosprincipaismotivosdousodefunesfriend.
C++permitesobrecarregarosoperadoresdeinseroeextraodefluxo:>>e<<.Parasobrecarregarestes
operadores,devemospassarcomoparmetroeretornarofluxocorrespondente(ostreamouistream),para
queestesoperadorespossamserencadeados.padrotornarestesoperadores frienddaclasseparaoqual
estsendosobrecarregado.Vejamosasintaxedasobrecargadesteoperador:
45
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Sobrecarregando o operador []
Ooperador[],dendicedearray,tambmpodesersobrecarregado.Istonospermiteutilizarndicesdearray
comosobjetospararetornardadosdoarmazenamentointernodoobjeto.Parasobrecarregaresteoperador
devemoscriarummtododaseguinteforma:
Ondicedooperadorpassadoparaomtodopeloseuargumentointeiro,nonossocasoindex.
Sobrecarregando o operador =
Asobrecargadooperadordeatribuio,=,temamesmaimportnciaeusodacriaodeconstrutoresde
cpia.Casoesteoperadornosejasobrecarregado,ocompiladorutilizaooperadorpadro,quesimplesmente
copia o objeto membro a membro, causando os mesmos problemas com membros ponteiro que vimos
anteriormente.Parasobrecarregaresteoperador,criamosummtodonaclassecomaseguintesintaxe:
Modelos de classes
OC++permitecriarmodelosdeclasses(classtemplates)damesmaformaquecriamosmodelosdefuno,
paradarumamaiorgeneralizaoaonossocdigo.Estesmodelosnospermitemusarummesmoalgoritmo
paravriostiposdedados,evitandoreescreverumaclasseparacadatipo.Paracriarmodelosdeclasses,
procedemosdeformaanlogacriaodemodelosdefuno:
template <lista_de_parmetros>
class nome_da_classe
{
.
.
.
};
AbaixoveremosaclasseTStack,umapilhagenrica.
public:
TStack();
TStack(const T &e);
TStack(const TStack &stack);
~TStack();
TStack & operator=(const TStack &stack);
46
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
bool isEmpty();
void push(T &e);
T pop();
};
if (stack.next != NULL)
next = new TStack(stack.next);
else
next = new TStack();
}
if (stack.next != NULL)
next = new TStack(stack.next);
else
next = new TStack();
return *this;
}
return ret;
}
47
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
if (next != NULL)
{
next->push(e);
}
else
{
element = e;
next = new TStack();
}
}
if (next != NULL)
{
if (next->next != NULL)
e = next->pop();
else
{
e = next->element;
delete next;
}
}
else
{
e = NULL;
}
return e;
}
Devemosnotarosseguintesaspectosnestaimplementao:porutilizarmembrosponteiros,aclassedeveter
um construtordecpia,umdestrutor(para liberar amemriaalocada para oponteiro) eooperador de
atribuiosobrecarregado(paragarantiracpiadoobjetonaatribuio).
Almdapalavrachavetypename,podeservistaadeclaraodeumaclassetemplateutilizandoapalavra
chaveclassemseulugar.Estaformadeimplementao,noentanto,estemdesuso,poistypenamemuito
maisgenricodoqueclass.
Osmodelosdeclassetambmpermitemmaisdeumtipodedadoscomoparmetrodomodelo.Oseguinte
cdigomostracomodefinirummodelodeclassedependentededoistiposdedados:
Note que os outros parmetros podem ser tipos de dados genricos (declarados com typename) como
tambmtiposespecficos(charouint,porexemplo).
48
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
TScreenrepresentandoateladojogo.
TBall, TBlock e TBarrepresentandoosspritesdojogo.Estasclassesdevemprovercomunicao
comTScreen,comomtodosparaseremdsenhados,etc.
TGameclasseparacontrolaradinmicadojogo.Sedesejado,podeconternveis.
TPlayerpossuimtodosparainteraocomojogadoreguardaassuasinformaes.
Devemos tambm criar um arquivo que contm a funo main e todos os objetos necessrios para o
funcionamentodojogo.Asclassesacimasoapenassugestes,eimportanteperceberquepodemos(na
realidadedevemos)criarclassesauxiliarespararepresentartiposdedadosutilizadospelasclassesprincipais,
porexemplo.
Notequeprovavelmentesernecessriosobrecarregaroperadores(podemossobrecarregarosoperadores>>e
<< para conectar aentradaesadadojogocom osnossosobjetos).Noesquea tambm quedevemos
implementarasnossasclassescomnomnimo:
Construtorpadro
Construtordecpia
Operadordeigualdadesobrecarregado
Destrutor
49
Captulo IV
Herana em C++
VejamosumexemplodecomoutilizarheranaemC++.DefiniremosumaclassechamadaTShape.Apartir
destaclasse,criaremosTBlock(bloco)eTBall(bola):
class TShape
{
.
.
.
};
Comopodemosperceber,paracriarumaclassequeherdadeoutra,bastaapenasincluir:
: modificador nome_superclasse
apsonomedasubclasse.Omodificadorserveparaespecificarcomoasuperclasseservistadentroda
subclasse.Omodificadorpublicindicaqueosmembrospblicosdasuperclassecontinuamsendopblicosna
subclasse. Analogamente, os modificadores protected e private tornam os membros da superclasse
protegidosouprivadosnasubclasse.
Vimosnocaptuloanterior,comosobreporosmtodosdeumaclasse.Quandocriamosumaclassederivada,
tambm podemossobreporosmtodosdasuperclasse, inclusiveosconstrutores edestrutores. Quandoa
superclassenotemumconstrutordefinido,aocriarmosumobjetodasubclasse,oconstrutordasuperclasse
chamadoautomaticamente.Masquandotemosconstrutoresdefinidosnasuperclasse,devemosespecificar
52
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos
quaisargumentosseropassadosparaessesconstrutores,quandoumobjetodasubclassecriado.Istofeito
utilizandoseinicializadores:
class TShape
{
protected:
int x;
int y;
char *name;
public:
TShape(int x1, int y1, const char *n);
~TShape();
};
TShape::~TShape()
{
delete[] name;
}
TBlock::~TBlock()
{
delete[] pattern;
}
Note que utilizamos :TShape(x1, y1, block) para chamar o construtor da superclasse. Os
construtoresdassuperclassessosemprechamadosantesdosconstrutoresdassubclasses.Comosdestrutores
ocorreoinverso:osdestrutoresdassubclassessochamadosantesdosdassuperclasses.
Asobreposiodemtodosocorredeformasemelhante,adiferenaque,parachamarmosmtodosda
superclassedentrodasubclasseutilizamos:nome_superclasse::metodo(parametros).
53
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Comojvimos,possveltermosponteirosparaobjetosdeumaclasse.OC++tambmpermitequeponteiros
paraumasuperclasseapontemparaobjetosdeumaclassederivada,apesardenopoderacessarosmembros
especficosdesta.Esteprocesso,deumponteiropoderapontarparadiversosobjetosderivadosdistintos
chamadopolimorfismo.Entovocdeveestarpensando:oqueacontecesetivermosummtodosobreposto
na subclasse e, com um ponteiro da superclasse apontando para um objeto da subclasse, chamarmos o
mtodo?Estconfuso?Vejamosumexemploqueilustreistomelhor:
class TShape
{
protected:
int x;
int y;
char *name;
public:
TShape(int x1, int y1, const char *n);
~TShape();
void draw();
};
void TShape::draw()
{
cout << Drawing a shape << endl;
}
void TBlock::draw()
{
cout << Drawing a block << endl;
}
int main()
{
TBlock block(10, 20, ####);
TShape shape(10, 20, shape);
TShape *shapePtr;
shapePtr = &shape;
shapePtr->draw();
shapePtr = █
shapePtr->draw();
return 0;
}
Asadadoprogramaser:
54
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos
Drawing a shape
Drawing a shape
Porque?Bem,oponteiroshapePtrdotipoTShapee,apesardepodermosapontarparaumobjetodo
tipo TBlock (afinal um TBlock um TShape), ao chamarmos um mtodo atravs do ponteiro, o
compiladorfarumaligaoesttica(staticbidingligaoemtempodecompilao)davarivelponteiro
comomtododesuaclasse.IstofarcomqueomtododaclasseTShapesejachamadoindependentemente
deparaqualobjetooponteiroaponte(afinal,emtempodecompilaonopossvelsaberocontedodo
ponteiro).
Ento,comochamaramosomtodocorreto?OC++ofereceumaalternativaquepermitequealigaodo
objetocomomtodosejafeitadinamicamente(dynamicbidingligaoemtempodeexecuo).Istofeito,
declarandoomtododasuperclassecomo virtual.Quandodeclaramos ummtododestaforma,estamos
avisandoaocompiladorparafazeraligaodoobjetocomomtodoemtempodeexecuo,paraqueo
mtododoobjetocorretosejachamado.SenadeclaraodaclasseTShapedoexemploanterior,tivssemos
aseguintelinha:
Asadadoprogramaseria:
Drawing a shape
Drawing a block
IstoquerdizerqueshapePtr>draw()chamaTShape::draw()quandoshapePtrapontaparaum
objetodotipo TShape echama TBlock::draw() quando shapePtr apontaparaumobjetodotipo
TBlock.
Portanto,padroparaosprogramadoresC++definirsempreosdestrutoresdeumaclassecomovirtuais.
Destaforma,estaremosassegurandoqueodestrutorcorretoserchamadoquandoumobjetodeumaclasse
derivadafordestrudo.
Classes abstratas
Umaclasseditaabstrataquandopossuiumoumaismtodosquenoforamimplementados(chamados
mtodos virtuaispuros).Istosignificaquenopodemosinstanciarumobjetodestaclasse,masapenasde
suasclassesderivadas,ondeestesmtodosseroimplementados.Continuemoscomnossoexemplo,emque
temosumaclasseTShapeeumaclasseTBlock.VamosincluirasclassesTBalleTBarqueherdamde
TShapetambm.Portanto,nonossoprograma,todoshapeouumbloco,ouumabola,ouumabarra,eque
qualquerobjetoqueherdedaclasseTShapetenhaquepossuiromtododraw().Entodevemosdeclararo
mtodo draw() de TShape como virtual puro, transformando a classe TShape em classe abstrata e
forandosoassubclassesaimplementaremomtodo.Istofeitocolocando=0nolugardocorpodomtodo
(indicandoqueomtodonopossuiimplementaonestaclasse)comoveremosaseguir:
class TShape
{
public:
.
.
.
virtual void draw()=0;
};
55
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
public:
.
.
.
void draw();
};
void TBlock::draw()
{
cout << Drawing a block << endl;
}
void TBall::draw()
{
cout << Drawing a ball << endl;
}
void TBar::draw()
{
cout << Drawing a bar << endl;
}
Comovimos,todasasclassesderivadasdeTShapedeveroimplementaromtododraw().
Herana mltipla
OC++permitequeumaclasseherdedevriasoutras,incorporandoosmembrosdasduasclasses.Aherana
mltiplacontestadaporalgunsprogramadores,poisistofacilitaoconflitoentreosmembrosdasclasses.
Vejamoscomodeclaramosumaclassecomheranamltipla:
56
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos
Outroproblemaqueenfrentamoscomaheranamltiplaque,quandocriamosumobjetodasubclasse,
estamoscriandoumobjetointernodecadasuperclasse.Eseassuperclassesherdaremdeumamesmaclasse
base?Serocriadosvriosobjetosinternosdaclassebase(notequeserocriadosvrios objetosinternos
idnticos),equandochamarmosummtododestaclassebase,ocompiladornosaberdequaldosobjetos
internoschamaromtodo.Pararesolveristo,asclassesdevemfazerumaheranavirtualdaclassebase,de
formaqueumnicoobjetodaclassebasesercriado:
Usarheranavirtualeliminaoconflitodeusarmosclassesbasecompartilhadas.Maseseassuperclassesde
TScreenObjectspossuremconstrutoresquepassemargumentosdistintosparaaclasseTShape?Como
oprogramaspodecriarumobjetocompartilhadodaclasseTShape,oC++desativaapassagemautomtica
deparmetros(cominicializadores)dasclassesintermediriasparaaclassebasevirtualenoseulugarchama
oconstrutorpadrodestaclasse.Vejamosesteexemplo:
57
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
AssimgarantimosainicializaocorretadosobjetosdaclasseTScreenObjects.
Excees
Exceessoerrosdetempodeexecuo,ouseja,nosobugs(errosdalgicadoprograma),massimerros
geradospelamanipulaodedadosinadequados(geralmentefornecidosporusurios).Vejamosumexemplo
destetipodeerro:
int main ()
{
int num1, num2;
return 0;
}
Nesteexemplo,apesardalgicaestarcorreta,poderamosterumerrodetempodeexecuo(runtimeerror)
casoousurioinformasseovalorzeroparaosegundonmero.
Paraestestiposdeproblemaqueexistemasexcees.Omecanismodeexcees nospermitetentar
executar(try)umdeterminadocdigo,casoocdigonopossaserexecutadolanamos(throw)uma
exceoquesercapturada(catch)etratadaemoutrapartedocdigo.Vejamoscomoistofunciona:
int main ()
{
int num1, num2;
try
{
if (num2 == 0)
{
throw string(Erro: diviso por zero.);
}
58
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos
}
catch(string str)
{
cout << str << endl;
}
return 0;
}
Nocdigoacima,apartesensvel(ondepodeocorrerumaexceo),colocadadentrodeumblocotry.
Casohajaumerro,lanamosumaexceocom throw,eofluxodoprogramaserdesviadoparaforado
bloco try.Apartirdestemomento,oprogramairprocurarumbloco catch quecaptureumaexceodo
mesmo tipo que a lanada (no nosso caso string). Caso no encontre, passa o fluxo do programa
funo/mtodoquechamouocdigoquelanouaexceo,subindopelapilhadechamadasdefunes(call
stack)atafunomain.Senafunomaintambmnohouverumblococatchparaestetipodeexceo,o
programaencerrado.
Comovocjdeveterpercebido,podemoslanarumaexceodequalquertipodedado(inclusiveclasses
especficasparatratamentodeexcees,comcdigoemensagensdeerro,etc..).OANSI/ISOC++define
umaclassedeexceopadrochamada exception.Estaclassepossuiummtodoconstantechamado
what()queretornaumconst char*contendoumamensagemdeerrodaexceo.Portanto,podemos
criarnossasclassesdeexceoherdandodaclasse exceptionesobrescrevendoomtodowhat()para
queexibaamensagemdeerroadequada.Vejamosumexemplo:
int main ()
{
int num1, num2;
try
{
if (num2 == 0)
{
throw TDivideByZeroException();
}
return 0;
59
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Podemos observar que o bloco catch (exception &e){...} captura uma exceo do tipo
exceptionbemcomotodasqueherdamdela,comoTDivideByZeroException.
Mascomotratarexceesinesperadas?Porpadro,oprogramachamaafunounexpectedquandoencontra
uma exceo que no capturada por nenhum bloco catch. Esta funo, por sua vez chama a funo
terminatequechamaabort.Oarquivodecabealhoexceptionpossuiasfunesset_unexpectede
set_terminate, para definir funes de tratamento de excees inesperadas. Podemos definir uma
funo comset_unexpected eestafunopodelevantarumaexceoquepossasercapturada por
algum bloco catch ou encerrar o programa, chamando terminate, exit ou abort. Isto uma forma de
converterumaexceoinesperadaparaumaexceoquepossamostratar.Podemostambmutilizarafuno
set_terminateparadefinirumafunoaserchamadaantesqueoprogramaterminedeformaanormal.
Exemplo:
void exitFunction()
{
cout << Antes de terminar, imprimo isto. << endl;
exit(1);
}
int main ()
{
set_terminate(exitFunction);
try
{
throw string(Erro);
}
catch(float f){}
return 0;
}
Nestecaso,comoaexceonofoicapturada,oprogramaterminou,masafunoexitFunction()foi
chamadaantes.
Podemostambmcriarblocoscatchquecapturemliteralmentequalquercoisa.Istofeitodaseguinteforma:
catch (...)
{
.
.
.
}
Assim,qualquerexceolevantadasercapturadaporestebloco.
60
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos
TScreen TShape
Podemos,pensandoanalogamente,verificartodoonossoprogramaembuscadegruposdeclassesquepodem
sergeneralizadas,aumentandoareusabilidadedonossocdigo.
61
Captulo V
NotequeparautilizaroselementosdaRTTIdeC++necessrioincluiroarquivodecabealhotypeinfo.
O operador dynamic_cast
Esteoperadorutilizadoquandonecessitamosconverterumponteirodeumaclassebaseparaumaclasse
derivada,parapoderutilizarosmembrosdaclassederivada.Istospossvel,seoponteirodaclassebase
estiverapontandoparaumobjetodaclassederivada.Senoforocaso,ooperadorretornaNULL(ponteiro
nulo).Vejamosumexemplo:
int main()
{
TBall bola;
TShape *shapePtr = &bola;
TBall *ballPtr = NULL;
if (ballPtr != NULL)
{
cout << cast realizado com suceso! << endl;
}
else
{
cout << no foi possvel realizar o cast! << endl;
}
return 0;
}
NotequeumponteirodotipoTShapepodeapontartantoparaumobjetoTShapequantoparaobjetosdas
classesderivadas,comoTBall.Oqueooperadordynamic_castfazutilizarasinformaesdetempode
execuodecadatipoparasabersepossvelrealizarocast.
63
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
int main()
{
TBall bola;
TShape *shapePtr = &bola;
TBall *ballPtr = NULL;
if (typeid(*shapePtr) == typeid(TBall))
{
cout << cast dinmico pode ser realizado! << endl;
ballPtr = dynamic_cast <TBall *> (shapePtr);
}
else
{
cout << cast dinmico no pode ser realizado! << endl;
}
return 0;
}
Neste caso, comparamos o tipo do objeto apontado por shapePtr com o tipo TBall, para nos
certificarmosqueshapePtrapontaparaumobjetodotipoTBall,antesdefazerocastdinmico.Nofim
do programa exibimos o nome do tipo do objeto apontado por shapePtr, que TBall (em alguns
compiladoresexisteumavariaodestenome,evocpoderiaver4TBall,porexemplo).
64
CaptuloVRecursosavanadosdoC++:RTTIeSTL
Contineres:classesutilizadasparaarmazenaremanipularconjuntosdeobjetos.
Iteradores:ponteirosespeciaisparaoscontineresdaSTL,quenospermitempercorrerosdadosdo
continer.
Algoritmos:conjuntodefunesquepodemosaplicaraoscontineresdaSTL.
Objetosfuno:podemospersonalizarocomportamentodealgunsalgoritmosdaSTL,utilizando
objetosfuno,oufunctores.
VeremosagoracadaumdosgruposdeelementosdaSTLdetalhadamente.
Contineres da STL
A STL do C++ possui onze contineres. Antes de conheclos, veremos os tipos comuns a todos os
contineres,quesoutilizadosparacriarnossasvariveis(nalistaabaixo,continerrepresentaonomedo
continer):
continer::value_type:retornaotipodoelementodocontiner.
continer::reference:retornaumarefernciaparaocontiner.equivalenteaT&.
continer::const_reference : retorna uma referncia constante para o continer.
equivalenteaconst T&.
continer::iterator:otipodoiteratordocontiner.Umiteratorumageneralizaopara
T*.
continer::const_iterator:otipodoiteratorconstantedocontiner.umageneralizao
paraconst T*.
continer::difference_type :umtipointeirocomsinalquerepresentaadistnciaentre
iteradores.
continer::size_type :umtipointeirosemsinalquerepresentaotamanhodeobjetosde
dados,nmerodeelementosendices.
Almdestestipos,existemumconjuntodemtodosquesocomunsatodososcontineres(excetobitset)e
seromostradosabaixo:
begin:retornaumiteradorparaoprimeiroelementodocontiner.
end:retornaumiteradorparaoelementoapsoltimo,docontiner.
rbegin:retornaumiteradorreversoparaoprimeiroelementodocontiner.
rend:retornaumiteradorreversoparaoelementoapsoltimo,docontiner.
size:retornaonmerodeelementosdocontiner.
maxsize:retornaotamanhomximodocontiner.
empty:retornatrueseocontinerestivervazio.
swap:permutaocontedodedoiscontineres.
Operadorescondicionais==, !=, <, >, <= e >=:utilizadosparacomparardoiscontineres.
65
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
AgoraqueconhecemosumpoucodoscontineresdaSTL,veremoscadaumdetalhadamente.Abaixosegue
umalistacomonome,descrio,interfaceeoarquivodecabealhoassociadoacadacontiner:
vector
Descrio Representaumarrayunidimensional.Aprincipalvantagemdeutilizareste
continer,emvezdeumarray,quepodemosalteraroseutamanhofacilmente
emtempodeexecuo.
Arquivodecabealho vector
Interface template <class T, class Allocator = allocator<T> >
class vector
{
public:
// Typedefs
typedef T value_type;
typedef Allocator allocator_type;
typedef typenameAllocator::referencereference;
typedeftypenameAllocator::const_reference
const_reference;
classiterator;
classconst_iterator;
typedeftypenameAllocator::size_typesize_type;
typedeftypenameAllocator::difference_type
difference_type;
typedeftypenamestd::reverse_iterator<iterator>
reverse_iterator;
typedeftypenamestd::reverse_iterator<constiterator>
const_reverse_iterator;
// Construtores/Cpia/Destrutores
explicitvector(constAllocator&=Allocator());
explicitvector(size_type,constAllocator&=
Allocator());
vector(size_type,constT&,constAllocator&=
Allocator());
vector(constvector<T,Allocator>&);
template<classInputIterator>
vector(InputIterator,InputIterator,
constAllocator&=Allocator());
~vector();
vector<T,Allocator>&operator=(const
vector<T,Allocator>&);
template<classInputIterator>
voidassign(InputIteratorfirst,InputIteratorlast);
voidassign(size_type,const);
allocator_typeget_allocator()const;
// Iterators
iteratorbegin();
const_iteratorbegin()const;
iteratorend();
const_iteratorend()const;
reverse_iteratorrbegin();
const_reverse_iteratorrbegin()const;
66
CaptuloVRecursosavanadosdoC++:RTTIeSTL
// Capacidade
size_type size () const;
size_type max_size () const;
//Modificadores
voidpush_back(constT&);
voidpop_back();
iteratorinsert(iterator,constT&);
voidinsert(iterator,size_type,constT&);
template<classInputIterator>
voidinsert(iterator,InputIterator,InputIterator);
iteratorerase(iterator);
iteratorerase(iterator,iterator);
voidswap(vector<T,Allocator>&);
voidclear()
};
list
Descrio Representaumalistaduplamenteencadeada.Devemosutilizarestecontiner
quandonecessitamosdefreqentesinsereseremoesnomeiodalista,pois
estecontinerofereceumtempodeacessoconstanteaoselementos,independente
dotamanhodalista.
Arquivodecabealho list
Interface template<classT,classAllocator=allocator<T>>
classlist
{
public:
// typedefs
classiterator;
classconst_iterator;
typedeftypenameAllocator::referencereference;
typedeftypenameAllocator::const_reference
const_reference;
typedeftypenameAllocator::size_typesize_type;
typedeftypenameAllocator::difference_type
67
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typenamestd::reverse_iterator<iterator>
reverse_iterator;
typedeftypename
std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Construtores/Cpia/Destrutores
explicitlist(constAllocator&=Allocator());
explicitlist(size_type);
list(size_type,constT&,constAllocator&=
Allocator())
template<classInputIterator>list(InputIterator,
InputIterator,constAllocator&=
Allocator());
list(constlist<T,Allocator>&x);
~list();
list<T,Allocator>&operator=(const
list<T,Allocator>&);
template<classInputIterator>voidassign
(InputIterator,InputIterator);
voidassign(size_typen,constT&);
allocator_typegetallocator()const;
// Iterators
iteratorbegin();
const_iteratorbegin()const;
iteratorend();
const_iteratorend()const;
reverse_iteratorrbegin();
const_reverse_iteratorrbegin()const;
reverse_iteratorrend();
const_reverse_iteratorrend()const;
// Capacidade
boolempty()const;
size_typesize()const;
size_typemax_size()const;
voidresize(size_type);
voidresize(size_type,T);
// Modificadores
voidpush_front(constT&);
voidpop_front();
voidpush_back(constT&);
voidpop_back();
68
CaptuloVRecursosavanadosdoC++:RTTIeSTL
// Operaes especiais
voidsplice(iterator,list<T,Allocator>&);
voidsplice(iterator,list<T,Allocator>&,
iterator);
voidsplice(iterator,list<T,Allocator>&,
iterator,iterator);
voidremove(constT&);
template<classPredicate>voidremove_if
(Predicate);
voidunique();
template<classBinaryPredicate>
voidunique(BinaryPredicate);
voidmerge(list<T,Allocator>&);
template<classCompare>
voidmerge(list<T,Allocator>&,Compare);
voidsort();
template<classCompare>voidsort(Compare);
voidreverse();
};
deque
Descrio Doinglsdoubleendedqueue,representaumafilacomdoisfinais,ouseja,
podemosadicionarouremoverelementosemambasasextremidades.Possui
operaesdeinseroeapagamentocomtempoconstanteparaoincioefinalda
fila,masotempodeacessocrescelinearmentecomotamanhodafilaparaacessos
aelementosdomeio.
Arquivodecabealho deque
Interface template<classT,classAllocator=allocator<T>>
classdeque
{
public:
//Typedefs
classiterator;
classconst_iterator;
typedefTvalue_type;
typedefAllocatorallocator_type;
typedeftypename
Allocator::referencereference;
typedeftypename
Allocator::const_referenceconst_reference;
typedeftypename
Allocator::size_typesize_type;
typedeftypename
Allocator::difference_typedifference_type;
typedeftypename
69
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
std::reverse_iterator<iterator>
reverse_iterator;
typedef typename
std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Construtores/Cpia/Destrutores
explicit deque (constAllocator&=Allocator());
explicitdeque(size_type);
deque(size_type,constT&value,
constAllocator&=Allocator());
deque(constdeque<T,Allocator>&);
template<classInputIterator>
deque(InputIterator,InputIterator,
constAllocator&=Allocator());
~deque();
deque<T,Allocator>&operator=
(constdeque<T,Allocator>&);
template<classInputIterator>
voidassign(InputIterator,InputIterator);
voidassign(size_type,constT&);
allocator_typegetallocator()const;
// Iterators
iteratorbegin();
const_iteratorbegin()const;
iteratorend();
const_iteratorend()const;
reverse_iteratorrbegin();
const_reverse_iteratorrbegin()const;
reverse_iteratorrend();
const_reverse_iteratorrend()const;
//Capacidade
size_typesize()const;
size_typemax_size()const;
voidresize(size_type);
voidresize(size_type,T);
boolempty()const;
referencefront();
const_referencefront()const;
referenceback();
const_referenceback()const;
// Modificadores
voidpush_front(constT&);
voidpush_back(constT&);
iteratorinsert(iterator,constT&);
voidinsert(iterator,size_type,constT&);
70
CaptuloVRecursosavanadosdoC++:RTTIeSTL
template <classInputIterator>
voidinsert(iterator,InputIterator,
InputIterator);
voidpop_front();
voidpop_back();
iteratorerase(iterator);
iteratorerase(iterator,iterator);
voidswap(deque<T,Allocator>&);
voidclear();
};
queue
Descrio Representaumafilaemquepodemosfazerinseresnoincioeremover
elementosdofim.umaformarestritadocontinerdeque.
Arquivodecabealho Queue
Interface template<classT,classContainer=deque<T>>
classqueue
{
public:
// typedefs
typedeftypenameContainer::value_typevalue_type;
typedeftypenameContainer::size_typesize_type;
typedefContainercontainer_type;
// Construtores/Cpia/Destrutores
explicitqueue(constContainer&=Container());
// Acesso
boolempty()const;
size_typesize()const;
value_type&front();
constvalue_type&front()const;
value_type&back();
constvalue_type&back()const;
voidpush(constvalue_type&);
voidpop();
};
priority_queue
Descrio Representaumafiladeprioridade.Aordemdoselementosdeterminadapelo
operadormenorque,<oupelocomparadorcompare.Istosignificaqueos
objetosguardadosnestecontinerdevemteresteoperadorsobrecarregadoalmde
umconstrutordecpia,destrutoreoperador=.
Arquivodecabealho queue
Interface template<classT,classContainer=vector<T>,
classCompare=less<typename
Container::value_type>>
classpriority_queue
{
public:
// typedefs
typedeftypenameContainer::value_typevalue_type;
71
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
typedef typenameContainer::size_typesize_type;
typedefContainercontainer_type;
// Construct
explicitpriority_queue(constCompare&=Compare(),
constContainer&=
Container());
template<classInputIterator>
priority_queue(InputIteratorfirst,
InputIteratorlast,
constCompare&=Compare(),
constContainer&=Container());
boolempty()const;
size_typesize()const;
constvalue_type&top()const;
voidpush(constvalue_type&);
voidpop();
};
stack
Descrio Representaumapilha,comoperaesparaempilhar,desempilhareverotopoda
pilha.
Arquivodecabealho stack
Interface template<classT,classContainer=deque<T>>
classstack
{
public:
// typedefs
typedeftypenameContainer::value_typevalue_type;
typedeftypenameContainer::size_typesize_type;
typedefContainercontainer_type;
// Construtor
explicitstack(constContainer&=Container());
// Acesso
boolempty()const;
size_typesize()const;
value_type&top();
constvalue_type&top()const;
voidpush(constvalue_type&);
voidpop();
};
set
Descrio Representaumconjuntodeobjetos,semelhanteaumconjuntomatemtico,sendo
quecadaelementodoconjuntodevesernico.Implementaasoperaescomuns
sobreconjuntos,comounio,interseo,etc.
Arquivodecabealho set
Interface template<classKey,classCompare=less<Key>,
classAllocator=allocator<Key>>
classset
{
72
CaptuloVRecursosavanadosdoC++:RTTIeSTL
public:
// typedefs
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef Allocator allocator_type;
typedef typenameAllocator::referencereference;
typedeftypenameAllocator::const_reference
const_reference;
classiterator;
classconst_iterator;
typedeftypenameAllocator::size_typesize_type;
typedeftypenameAllocator::difference_type
difference_type;
typedeftypenamestd::reverse_iterator<iterator>
reverse_iterator;
typedeftypenamestd::reverse_iterator<const_iterator>
const_reverse_iterator;
//Construtores/Cpia/Destrutor
explicitset(constCompare&=Compare(),
constAllocator&=Allocator());
template<classInputIterator>
set(InputIterator,InputIterator,
constCompare&=Compare(),
constAllocator&=Allocator());
set(constset<Key,Compare,Allocator>&);
~set();
set<Key,Compare,Allocator>&operator=
(constset<Key,Compare,Allocator>&);
allocator_typeget_allocator()const;
// Iterators
iteratorbegin();
const_iteratorbegin()const;
iteratorend();
const_iteratorend()const;
reverse_iteratorrbegin();
const_reverse_iteratorrbegin()const;
reverse_iteratorrend();
const_reverse_iteratorrend()const;
// Capacidade
boolempty()const;
size_typesize()const;
size_typemax_size()const;
// Modificadores
pair<iterator,bool>insert(constvalue_type&);
iteratorinsert(iterator,constvalue_type&);
template<classInputIterator>
voidinsert(InputIterator,InputIterator);
voiderase(iterator);
73
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
// Observao de elementos
key_compare key_comp () const;
value_compare value_comp () const;
pair<iterator,iterator>equal_range(constkey_type&)
const;
iteratorfind(constkey_type&)const;
iteratorlower_bound(constkey_type&)const;
iteratorupper_bound(constkey_type&)const;
};
multiset
Descrio Ocontinermultisetrepresentaumconjunto(semelhanteaoset)emqueos
elementosnoprecisamsernicos.
Arquivodecabealho set
Interface template<classKey,classCompare=less<Key>,
classAllocator=allocator<Key>>
classmultiset
{
public:
// typedefs
typedefKeykey_type;
typedefKeyvalue_type;
typedefComparekey_compare;
typedefComparevalue_compare;
typedefAllocatorallocator_type;
typedeftypenameAllocator::referencereference;
typedeftypename
Allocator::const_referenceconst_reference;
classiterator;
classconst_iterator;
typedeftypenameAllocator::size_typesize_type;
typedeftypename
Allocator::difference_typedifference_type;
typedeftypenamestd::reverse_iterator<iterator>
reverse_iterator;
typedeftypename
std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Construtores/Cpia/Destrutores
explicitmultiset(constCompare&=Compare(),
constAllocator&=Allocator());
template<classInputIterator>
multiset(InputIterator,InputIterator,
74
CaptuloVRecursosavanadosdoC++:RTTIeSTL
// Iterators
iteratorbegin();
const_iteratorbegin()const;
iteratorend();
const_iteratorend()const;
reverse_iteratorrbegin();
const_reverse_iteratorrbegin()const;
reverse_iteratorrend();
const_reverse_iteratorrend()const;
// Capacidade
boolempty()const;
size_typesize()const;
size_typemax_size()const;
// Modificadores
iteratorinsert(constvalue_type&);
iteratorinsert(iterator,constvalue_type&);
template<classInputIterator>
voidinsert(InputIterator,InputIterator);
voiderase(iterator);
size_typeerase(constkey_type&);
voiderase(iterator,iterator);
voidswap(multiset<Key,Compare,Allocator>&);
voidclear();
// Observao de elementos
key_comparekey_comp()const;
value_comparevalue_comp()const;
};
map
Descrio Estecontinerrepresentaummapa,associaochave/valoremqueseusaachave
paraacessarovalorcorrespondente.Nestecontiner,cadachavedevesernica,de
modoquenopodemosterchavesrepetidas.
Arquivodecabealho map
Interface template<classKey,classT,classCompare=less<Key>
75
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
// typedefs
typedefKeykey_type;
typedeftypenameAllocator::pointerpointer;
typedeftypenameAllocator::const_pointer
const_pointer;
typedefTmapped_type;
typedefpair<constKey,T>value_type;
typedefComparekey_compare;
typedefAllocatorallocator_type;
typedeftypenameAllocator::referencereference;
typedeftypename
Allocator::const_referenceconst_reference;
classiterator;
classconst_iterator;
typedeftypename
Allocator::size_typesize_type;
typedeftypename
Allocator::difference_typedifference_type;
typedeftypenamestd::reverse_iterator<iterator>
reverse_iterator;
typedeftypename
std::reverse_iterator<const_iterator>
const_reverse_iterator;
classvalue_compare
:publicbinary_function<value_type,value_type,
bool>
{
friendclassmap<Key,T,Compare,Allocator>;
protected:
Comparecomp;
value_compare(Comparec):comp(c){}
public:
booloperator()(constvalue_type&,
constvalue_type&)const;
};
// Construtores/Cpia/Destrutores
explicitmap(constCompare&=Compare(),
constAllocator&=Allocator());
template<classInputIterator>
map(InputIterator,InputIterator,
constCompare&=Compare(),
constAllocator&=Allocator());
map(constmap<Key,T,Compare,Allocator>&);
~map();
map<Key,T,Compare,Allocator>&
operator=(constmap<Key,T,Compare,
Allocator>&);
allocator_typeget_allocator()const;
76
CaptuloVRecursosavanadosdoC++:RTTIeSTL
// Iterators
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Capacidade
bool empty() const;
size_typesize()const;
size_typemax_size()const;
//Acessoaoselementos
mapped_type&operator[](constkey_type&);
// Modificadores
pair<iterator,bool>insert(constvalue_type&);
iteratorinsert(iterator,constvalue_type&);
template<classInputIterator>
voidinsert(InputIterator,InputIterator);
voiderase(iterator);
size_typeerase(constkey_type&);
voiderase(iterator,iterator);
voidswap(map<Key,T,Compare,Allocator>&);
voidclear();
//Observaodeelementos
key_comparekey_comp()const;
value_comparevalue_comp()const;
//Operaessobremap
iteratorfind(constkey_value&);
const_iteratorfind(constkey_value&)const;
size_typecount(constkey_type&)const;
iteratorlower_bound(constkey_type&);
const_iteratorlower_bound(constkey_type&)const;
iteratorupper_bound(constkey_type&);
const_iteratorupper_bound(constkey_type&)const;
pair<iterator,iterator>equal_range(const
key_type&);
pair<const_iterator,const_iterator>
equal_range(constkey_type&)const;
};
multimap
Descrio Ocontinermultimaprepresentaummapa,semelhanteaocontinermap,mas
possibilitandooarmazenamentodemltiplosvaloresparaumamesmachave.
Arquivodecabealho map
Interface template<classKey,classT,classCompare=
less<Key>,classAllocator=allocator<pair<constKey,
T>>>
77
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
class multimap
{
public:
// typedefs
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef Compare key_compare;
typedef Allocator allocator_type;
typedef typenameAllocator::referencereference;
typedeftypename
Allocator::const_referenceconst_reference;
classiterator;
classconst_iterator;
typedeftypenameAllocator::size_typesize_type;
typedeftypename
Allocator::difference_typedifference_type;
typedeftypenamestd::reverse_iterator<iterator>
reverse_iterator;
typedeftypename
std::reverse_iterator<const_iterator>
const_reverse_iterator;
classvalue_compare
:publicbinary_function<value_type,value_type,bool>
{
friendclassmultimap<Key,T,Compare,Allocator>;
protected:
Comparecomp;
value_compare(CompareC):comp(c){}
public:
booloperator()(constvalue_type&,
constvalue_type&)const;
};
// Construtores/Cpia/Destrutores
explicitmultimap(constCompare&=Compare(),
constAllocator&=Allocator());
template<classInputIterator>
multimap(InputIterator,InputIterator,
constCompare&=Compare(),
constAllocator&=Allocator());
multimap(constmultimap<Key,T,Compare,
Allocator>&);
~multimap();
multimap<Key,T,Compare,Allocator>&operator=
(constmultimap<Key,T,Compare,Allocator>&);
allocator_typeget_allocator()const;
// Iterators
iteratorbegin();
const_iteratorbegin()const;
iteratorend();
const_iteratorend()const;
reverse_iteratorrbegin();
const_reverse_iteratorrbegin()const;
reverse_iteratorrend();
78
CaptuloVRecursosavanadosdoC++:RTTIeSTL
// Capacidade
bool empty () const;
size_typesize()const;
size_typemax_size()const;
//Modificadores
iteratorinsert(constvalue_type&);
iteratorinsert(iterator,constvalue_type&);
template<classInputIterator>
voidinsert(InputIterator,InputIterator);
voiderase(iterator);
size_typeerase(constkey_type&);
voiderase(iterator,iterator);
voidswap(multimap<Key,T,Compare,Allocator>&);
voidclear();
//Observaodeelementos
key_comparekey_comp()const;
value_comparevalue_comp()const;
pair<const_iterator,const_iterator>
equal_range(constkey_type&)const;
};
bitset
Descrio Estecontinerrepresentaumconjuntodebits(bitset),quepodemseracessados
individualmentecomooperadorcolchetes,[].Ofereceoperaeslgicasbitabit
bemcomomtodosdemanipulaodosbitsindividualmenteouemconjunto.
Arquivodecabealho bitset
Interface template<size_tN>
classbitset
{
public:
// bit reference
classreference
{
friendclassbitset;
public:
~reference();
reference&operator=(bool);
reference&operator=(constreference&);
booloperator~()const;
79
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
operator bool()const;
reference&flip();
};
//Construtores
bitset();
bitset(unsignedlong);
template<classcharT,classtraits,classAllocator>
explicitbitset(constbasic_string<charT,traits,
Allocator>,typenamebasic_string
<charT,traits,Allocator>
::size_type=0,typenamebasic_string
<charT,traits,Allocator>
::size_type=basic_string<charT,
traits,Allocator>::npos);
bitset(constbitset<N>&);
bitset<N>&operator=(constbitset<N>&);
// Operadores bit-a-bit
bitset<N>&operator&=(constbitset<N>&);
bitset<N>&operator|=(constbitset<N>&);
bitset<N>&operator^=(constbitset<N>&);
bitset<N>&operator<<=(size_t);
bitset<N>&operator>>=(size_t);
// Operadores no-membros
template<size_tN>bitset<N>
operator&(constbitset<N>&,constbitset<N>&);
template<size_tN>bitset<N>
operator|(constbitset<N>&,constbitset<N>&);
80
CaptuloVRecursosavanadosdoC++:RTTIeSTL
O modelo ato_ptr
AbibliotecapadrodoC++possuiummodelodeponteiro,auto_ptr,queoferecedesalocaoautomtica
damemriaquandooponetirosaidoescopo.Portanto,idealparautilizarmosponteiroslocaissemterque
nospreocuparmosemestarliberandomemriaquandosairmosdoescopo.importantelembrarque,comoo
ponteirochamaooperador delete automaticamente, nopodemos alocar arrays com auto_ptr,pois o
operadorchamadodeleteenodelete[].
Abaixosegueumexemplodecdigoqueutilizaoauto_ptr:
int main()
{
auto_ptr<TBlock> block;
block = new TBlock(10, 20, ####);
block->draw();
}
Aclassevalarrayummodelodeclasseprojetadoparaserutilizadocomvaloresnumricos.Semelhanteao
continervector,valarrayotimizadaparapermitiraplicaroperaesefunesmatemticasaoarray,como
mximodeeficincia.Vejamosumexemplodeuso:
int main()
{
valarray<int> array1(10);
valarray<int> array2(10);
importantesalientarqueapenasostiposnumricospodemserutilizadoscomvalarray,equeestaclasse
templatetambmpossuiimplementaesdasprincipaisfunesmatemticas,comoseno,cosseno,etc.
81
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
Iteradores
ASTLdeC++possuiumconjuntodeponteirosgenricosutilizadosparamanipularosdadosdoscontiners.
Damesmaformaqueousodecontineresnospermiteutilizarosalgoritmosindependentedotipodedados,
ositeradoresgeneralizamousodosalgoritmos,independentedocontiner.Ousodeiteradoressemelhante
aousodeponteirosdeformaqueocdigoabaixo:
int nums[10];
int *ptr;
Podeserescritodestaforma:
vector<int> nums(10);
vector<int>::iterator itr;
Ento, por que utilizar iteradores? Porque em contineres diferentes, operaes como se mover para o
prximoelementocausamresultadosdiferentestambm.Ento,utilizamositeradorescomqualquerfuno
STLsemnospreocuparmoscomotipodecontineremqueosdadosestoarmazenados,poisousodos
iteradoresomesmo.
VejamosalgunsiteradorespredefinidosdaSTL:
iterator:iteradorpadro.
ostream_iterator:iteradordemanipulaodefluxosostream,comocout.
istream_iterator:iteradordemanipulaodefluxosistream,comocin.
reverse_iterator:iteradorquepercorreosdadosemsentidoreverso.
insert_iterator:iteradordeinsero.
front_insert_iterator:insereelementosemumcontinerapartirdoincio.
back_insert_iterator:insereelementosemumcontinerapartirdofim.
Algoritmos da STL
OsalgoritmosdaSTLtrabalhamjuntocomositeradoresparamanipularosdadosdoscontineresdaSTL.
Comoositeradoressoidependentesdostiposdoscontineres,podemosaplicarosalgoritmosaositeradores
de qualquer continer, pois os iteradores que se encarregaro de percorrer internamente os dados
contineres.VejamososalgoritmosdaSTL:
accumulate
Descrio acumulavaloresdeoperaesmatemticassucessivas.
Arquivodecabealho numeric
Interface template <classInputIterator,classT>
Taccumulate(InputIteratorfirst,
InputIteratorlast,
Tinit);
82
CaptuloVRecursosavanadosdoC++:RTTIeSTL
template <classInputIterator,
classT,
classBinaryOperation>
Taccumulate(InputIteratorfirst,
InputIteratorlast,
Tinit,
BinaryOperationbinary_op);
copy
Descrio Copiadadosentrecontineres.
Arquivodecabealho algorithm
Interface template<classInputIterator,classOutputIterator>
OutputIteratorcopy(InputIteratorfirst,
InputIteratorlast,
OutputIteratorresult);
template<classBidirectionalIterator1,
classBidirectionalIterator2>
BidirectionalIterator2
copy_backward(BidirectionalIterator1first,
BidirectionalIterator1last,
BidirectionalIterator2result);
count e count_if
Descrio Contaonmerodeelementosdeumcontiner.Oalgoritmocount_ifcontaos
elementosdocontinerquesatisfazemumpredicado.
Arquivodecabealho algorithm
Interface template<classInputIterator,classT>typename
iterator_traits<InputIterator>::difference_type
count(InputIteratorfirst,InputIteratorlast,
constT&value);
template<classInputIterator,classT,classSize>
voidcount(InputIteratorfirst,InputIteratorlast,
constT&value,Size&n);
template<classInputIterator,classPredicate>typename
iterator_traits<InputIterator>::difference_type
count_if(InputIteratorfirst,InputIterator
last,Predicatepred);
template<classInputIterator,classPredicate,
classSize>voidcount_if(InputIterator
first,InputIteratorlast,Predicatepred,
Size&n);
equal
Descrio Comparaoselementosdedoiscontineresdentrodeumafaixadelimitadapelos
iteradoresfirstelast.
Arquivodecabealho algorithm
Interface template<classInputIterator1,classInputIterator2>
boolequal(InputIterator1first1,InputIterator1
last1,InputIterator2first2);
template<classInputIterator1,classInputIterator2,
classBinaryPredicate>
83
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
find
Descrio Procuraporumdeterminadovalornocontinereretornasuaprimeiraocorrncia.
Senoencontrar,retornaoiteratorlast.
Arquivodecabealho algorithm
Interface template <classInputIterator,classT>
InputIteratorfind(InputIteratorfirst,
InputIteratorlast,constT&value);
for_each
Descrio Aplicaumafunoatodososelementosdocontinernointervaloentrefirstelast.
Arquivodecabealho algorithm
Interface template<classInputIterator,classFunction>
voidfor_each(InputIteratorfirst,InputIteratorlast,
Functionf);
min_element e max_element
Descrio Retornamumiteradorqueapontaparaomnimoeomximoelementodo
continer,respectivamente.
Arquivodecabealho algorithm
Interface template<classForwardIterator>ForwardIterator
min_element(ForwardIteratorfirst,
ForwardIteratorlast);
template<classForwardIterator,classCompare>
InputIteratormin_element(ForwardIterator
first,ForwardIteratorlast,Comparecomp);
template<classForwardIterator>ForwardIterator
max_element(ForwardIteratorfirst,
ForwardIteratorlast);
template<classForwardIterator,classCompare>
ForwardIteratormax_element(ForwardIterator
first,ForwardIteratorlast,Comparecomp);
random_shuffle
Descrio Embaralhaaleatoriamenteoselementosdentrodointervalodeitaradoresfirste
last,comdistribuiouniforme.Poderecebercomoargumentoumobjetofuno
quegerenmerosaleatriosparaalteraradistribuio.
Arquivodecabealho algorithm
Interface template<classRandomAccessIterator>
voidrandom_shuffle(RandomAccessIteratorfirst,
RandomAccessIteratorlast);
template<classRandomAccessIterator,
classRandomNumberGenerator>
voidrandom_shuffle(RandomAccessIteratorfirst,
RandomAccessIteratorlast,
RandomNumberGenerator&rand);
84
CaptuloVRecursosavanadosdoC++:RTTIeSTL
remove
Descrio Removeelementosdeumcontinerquesatisfazemacondioelemento==valor.
Arquivodecabealho algorithm
Interface template <classForwardIterator,classT>
ForwardIteratorremove(ForwardIteratorfirst,
ForwardIteratorlast,constT&value);
replace
Descrio Substituielementosdeumcontinerquesoiguaisaold_valuepor
new_value.
Arquivodecabealho algorithm
Interface template<classForwardIterator,classT>
voidreplace(ForwardIteratorfirst,
ForwardIteratorlast,constT&old_value,
constT&new_value);
reverse
Descrio Inverteaordemdoselementosdocontinerqueestonointervalo(first,last).
Arquivodecabealho algorithm
Interface template<classBidirectionalIterator>
voidreverse(BidirectionalIteratorfirst,
BidirectionalIteratorlast);
rotate
Descrio Rotacionaoselementosdosegmentoquevaidefirstatmiddle1comos
elementosdosegmentodemiddleatlast.Oalgoritmorotate_copyretorna
umacpiadocontinerrotacionado.
Arquivodecabealho algorithm
Interface template<classForwardIterator>
voidrotate(ForwardIteratorfirst,
ForwardIteratormiddle,
ForwardIteratorlast);
template<classForwardIterator,classOutputIterator>
OutputIteratorrotate_copy(ForwardIteratorfirst,
ForwardIteratormiddle,
ForwardIteratorlast,
OutputIteratorresult);
search
Descrio searchprocuranointervalo(first1,last1)porumaseqnciaigualdo
intervalo(first2,last2),enquantosearch_nretornaumiteradorparaa
subseqnciadecountelementosquesoiguaisavalue.Podemostambm
especificarumpredicadoparaquesejatestadonabusca.
Arquivodecabealho algorithm
Interface template<classForwardIterator1,
classForwardIterator2>
85
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
ForwardIterator2first2,
ForwardIterator2last2,
BinaryPredicatebinary_pred);
template<classForwardIterator,
classSize,classT>
ForwardIteratorsearch_n(ForwardIteratorfirst,
ForwardIteratorlast,
Sizecount,constT&value);
template<classForwardIterator,
classSize,classT,classBinaryPredicate>
ForwardIteratorsearch_n(ForwardIteratorfirst,
ForwardIteratorlast,
Sizecount,constT&value,
BinaryPredicatepred)
sort
Descrio Ordenaoselementosdeumcontiner.Paracomparaoentreoselementosdo
continer,podeserutilizadoooperadormenorque,<,ouumobjetofuno
compare.
Arquivodecabealho algorithm
Interface template<classRandomAccessIterator>
voidsort(RandomAccessIteratorfirst,
RandomAccessIteratorlast);
template<classRandomAccessIterator,classCompare>
voidsort(RandomAccessIteratorfirst,
RandomAccessIteratorlast,Comparecomp);
swap e swap_ranges
Descrio swappermutaocontedodedoiscontineres,enquantoswap_ranges
permutaoselementosdointervalo(first1,last1)comoselementosdeum
intervalodomesmotamanhoqueiniciaemfirst2.
Arquivodecabealho algorithm
Interface template<classT>voidswap(T&a,T&b);
template<classForwardIterator1,
classForwardIterator2>
ForwardIterator2swap_ranges(ForwardIterator1first1,
ForwardIterator1last1,
ForwardIterator2first2);
transform
Descrio Aplicaumafunoaumintervalodevaloresdeumcontiner.
86
CaptuloVRecursosavanadosdoC++:RTTIeSTL
Arquivodecabealho algorithm
Interface template <classInputIterator,classOutputIterator,
classUnaryOperation>OutputIterator
transform(InputIteratorfirst,InputIteratorlast,
OutputIteratorresult,UnaryOperationop);
template<classInputIterator1,classInputIterator2,
classOutputIterator,classBinaryOperation>
OutputIteratortransform(InputIterator1first1,
InputIterator1last1,InputIterator2first2,
OutputIteratorresult,BinaryOperationbinary_op);
unique e unique_copy
Descrio Uniqueapagaosvaloresduplicadosconsecutivosemumcontiner.Unique_copy
copiaoprimeiroelementodecadagrupodeelementosiguaisconsecutivospara
result.Podemosutilizarumpredicadoparadeterminaraseleodosobjetos.
Arquivodecabealho algorithm
Interface template<classForwardIterator>ForwardIterator
unique(ForwardIteratorfirst,ForwardIteratorlast);
template<classForwardIterator,classBinaryPredicate>
ForwardIteratorunique(ForwardIteratorfirst,
ForwardIteratorlast,
BinaryPredicatebinary_pred);
template<classInputIterator,classOutputIterator>
OutputIteratorunique_copy(InputIteratorfirst,
InputIteratorlast,
OutputIteratorresult);
template<classInputIterator,classOutputIterator,
classBinaryPredicate>OutputIterator
unique_copy(InputIteratorfirst,InputIteratorlast,
OutputIteratorresult,
BinaryPredicatebinary_pred);
Objetos-funo
Alguns algoritmos daSTLrecebem classes especiais, quecontm funes para serem utilizadas com os
algoritmosdaSTL.Sochamadosdeobjetosfuno,quepodempossuirfunesnormaiseponteirospara
funes e objetos, sobrecarregando o operador parntesis, bastando para isto, definir um mtodo
operator()().
Objetosfunopodemserdivididosnosseguintesgrupos:
Geradores:objetosfunoquenorecebemargumentos.
Funesunrias:objetosfunoquerecebemumargumento.
Funesbinrias:objetosfunoquerecebemdoisargumentos.
Predicados:funesunriasqueretornamumvalorboleano.
Predicadosbinrios:funesbinriasqueretornamumvalorboleano.
87
DoCaoC++:umaabordagemdaEngenhariadeSoftware TiagoBarros
ExistemvriosobjetosfunopredefinidosnaSTLdeC++.Parautilizlos,deveremosincluiroarquivode
cabealho functional. Todas as operaes matemticas e lgicas simples possuem objetosfuno
predefinidos,observeatabelaabaixo:
Operador Objetofunocorrespondente
+ plus
- minus
* multiplies
/ divides
% modulus
- (unrio) negate
== equal_to
!= not_equal_to
> greater
< less
>= greater_equal
<= less_equal
&& logical_and
|| logical_or
! logical_not
88