Escolar Documentos
Profissional Documentos
Cultura Documentos
ObralicenciadasoblicenaCreativeCommonsAtribuioNoComercial Compartilhamentopelamesmalicena2.5Brasil
ndiceAnaltico
ndice Analtico
CAPTULOI ....................................................................................................................................................... 7
Seoprtica:definindonossoprojeto.............................................................................25
CAPTULOII ................................................................................................................................................... 27
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
ndiceAnaltico
RecursosavanadosdoC++:RTTIeSTL......................................................................62 ARTTI(runtimetypeinformation)..................................................................................63
Ooperadordynamic_cast...................................................................................................................................63 Utilizandoooperadortypeideaclassetype_info..............................................................................................63
ASTL(standardtemplatelibrary)...................................................................................65
ContineresdaSTL............................................................................................................................................65 Iteradores............................................................................................................................................................81 AlgoritmosdaSTL.............................................................................................................................................82 Objetosfuno....................................................................................................................................................87
Captulo I
CaptuloIEngenhariadeSoftwareEstruturada
O C++ bsico
Tipos: estruturas, unies e tipos enumerados
Comovoc j devesaber,quandonos referimos atipo,estamosfalandodotipodavarivel (poro de memriautilizadaparaguardardados).Ostiposdiferemnoformatocomoosdadossoarmazenadosena quantidade de memria utilizada. Tambm diferem na semntica, pois embora possam ter a mesma quantidade de memria, dois tipos podem guardar informaes de significado diferente. O C++ uma linguagemfortementetipada,oquesignificaqueasoperaessobrevariveissorealizadasapenasentre variveisdomesmotipo,oudetiposcompatveis.AlinguagemC++definevriostiposprprios,chamados tiposbsicos.Suascaractersticas,quevoc j deveconhecer,podemserencontradasnoApndiceA,de formaquenoprolongareiaquiumadiscussosobredeclaraoeutilizaodetiposbsicos.
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.
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
};
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,queTColorno umtipodedadossimples,deformaquepodemoscriartiposdedadoscompostosa partirdeoutrostiposcompostostambm. Unies Uma unio um tipo composto parecido com uma estrutura. A diferena que na unio, os diversos membroscompartilhamamesma readememria,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,nsatribumosumaconstantedotipo charuniovar.Posteriormente,acessamosaunio varatravsdoseumembroi,dotiposhort int.ComoaletraA representadainternamenteatravsdoseu cdigo numrico, quando acessamos a varivel como um tipo short int, teremos como retorno o valor numrico(docdigoASCII)daletraA.Portanto,oexemploacimaexibir: O codigo ASCII da letra A e 65 Tipos enumerados OstiposdedadosenumeradossoutilizadospararepresentartiposconceituaisquenoestopresentesnoC+ +padro.Porexemplo,pararepresentarotipodedadoscor,quepodeassumirosvaloresvermelho,verde, azul,amarelo,ciano,magenta,brancoepreto;poderamosutilizarumtipodedadosenumerado:
CaptuloIEngenhariadeSoftwareEstruturada enum TColor {clRed, clGreen, clBlue, clYellow, clCian, clMagenta, clWhite, clBlack }; 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(espaoreservado svariveis)deumprogramaemC++ divididaemtrs classes: Armazenamento automtico: onde as variveis de um bloco so alocadas e armazenadas quando o programaentranobloco.Seuescopolocal. Armazenamento esttico: rea dearmazenamento persistente. Os dados comarmazenamento esttico estodisponveisdurantetodaaexecuodoprograma.Istosignificaqueosdadosestticosnoso reinicializadosacadavezqueumafunochamada,comoocorrecomoarmazenamentoautomtico. Armazenamentolivre: readealocaodememriaemtempodeexecuo.Todavarivelalocadaem tempodeexecuo armazenadanesta rea. desumaimportnciaqueasvariveiscriadasnesta rea sejamdesalocadassemprequenoforemmaisserutilizadas.
Ligao Aligao(lincagem)sereferecapacidadedeumitemserutilizadoemdiversosarquivosdeumprograma. Variveisexternas(declaradasforadequalquerfuno)possuemtambmligaoexterna,oquesignificaque elasficamdisponveisaqualquerarquivodomesmoprograma.J asvariveisdeligaointernas esto disponveisnoarquivoemqueforamcriadas. Osconceitosvistosacimaestorelacionadosdeformanosistemtica,sendo svezesdifcildeseentender claramente. Portanto, abaixo segue uma lista das possveis associaes entre classes de armazenamento, escopoeligao: Tipodavarivel Variveisautomticas Variveisexternas Variveisexternasestticas Variveisexternasconstantes Variveisestticas Formadedeclarao Declaradasdentrodeumbloco Declaradasforadequalquerfuno Variveisexternasdeclaradascoma palavrachavestatic Variveisexternasdeclaradascoma palavrachaveconst Variveisautomticasdeclaradascoma palavrachavestatic Escopo Local Global Global Global Local Ligao Interna Externa Interna Interna Interna
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),que umtamanhomenordoque 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: short int numShort = 1234; long int numLong = 314153256; long int result; result = numShort + numLong; Cast explcito Utilizamos o cast explcito quando queremos informar ao compilador que no estamos fazendo uma conversoindesejada,etambmquandoostiposnosocompatveismasaconverso necessria.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 sum = static_cast <int> (pi) + num; const_cast<tipo>(expressoconstante): utilizadopararetiraraconstnciadeexpresses.Noexemplo abaixo,podemosdesconsiderarofatoqueconst_ptr umponteiroconstantequandoatribumoseleaum ponteironormal(nosepreocupe,veremosousodeponteirosmaisadiante): char * ptr; const char * const_ptr; . . . ptr = const_cast <char *> (const_ptr); reinterpret_cast<tipo>(expresso):oreinterpret_cast aformamaispoderosadeconversodetipos.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: pointer = reinterpret_cast <int *> (0xB0000000); 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)eser vistocomdetalhes 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,seublocodeinstruescorrespondenteser executado.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
avaliada como falsa; } A instruo switch Umaalternativaparaautilizaode ifelse aninhados ainstruo switch.Estainstruo utilizadapara desviosmltiplos,deumaformamaissinttica.Asintaxedoswitch: switch (expresso) { case valor1: instruo1; [break;] case valor2: instruo2; [break;] case valor3: instruo3; [break;] . . . default: instruo_padro; } Casoainstruobreaknosejautilizada,oprogramacontinuar executandoasinstruesdoprximo case atquehajaumbreakouqueacabeoblocoswitch. Os laos while e do-while Umlaowhileexecutaseublocodeinstruesenquantoasuaexpressoforavaliadacomoverdadeira(ou diferentedezero).Possuiasseguintessintaxes: while (expresso) { instrues; } ou do {
instrues; } while (expresso); Adiferena, quenolaowhilepuro,aexpresso avaliadaantesdeexecutarasinstrues,enquantono lao dowhile asinstrues soexecutadas eaexpresso avaliadanofinal(portantoasinstrues so executadaspelomenosumavez). O lao for
12
CaptuloIEngenhariadeSoftwareEstruturada Olaofor utilizadoquandodesejamosutilizarumndicenumrico,quesejaincrementado/decrementadoa cadaiterao.Suasintaxe: for (inicializao; expresso_de_teste; expresso_de_iterao) { instrues; } A inicializao executadaantesdecomearemasiteraesdolao. geralmenteondeinicializamosas variveisde ndicequeseroutilizadasnolao.Acadaiterao,aexpresso_de_teste avaliadaeolao 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. Instrues de controle de fluxo 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.
13
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Utilizando ponteiros
Parautilizarmososponteirosparaapontarparaumavarivel,utilizamosooperadorendereo,&: int um_inteiro = 10; double um_double = 3.14159; ponteiro_para_int = &um_inteiro; ponteiro_para_double = &um_double; Paraacessarocontedodasvariveisapontadaspeloponteiro,utilizamosooperador desreferncia,*,que tambmumasterisco: cout << O valor de um_inteiro : << *ponteiro_para_int; cout << O valor de um_double : << *ponteiro_para_double; 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: cout << O valor de um_inteiro : << &um_inteiro; Apesardepassarpelocompilador,esteexemploestariasemanticamenteincorreto,poisoqueseriaexibidoo endereodeum_inteiroenooseuvalor. Exemplo2: cout << O valor de um_inteiro : << *um_inteiro; Esteexemplocausaerrodecompilaopoisavarivelum_inteiro,apesardeteromesmotamanhodeum ponteiroeguardarumvalornumrico,nofoideclaradacomoponteiro,enopodeterseucontedoutilizado paraenderearmemria. Exemplo3: cout << O valor de um_inteiro : << &ponteiro_para_int; Nesteexemplo,estaramosexibindooendereodeponteiro_para_int,enoocontedodoendereo queeleaponta.Seestivssemosatribuindo&ponteiro_para_intparaumavarivel,comoestavarivel deveriaserdeclarada?Corretoserespondeu:int**ponteiro_duplo;Poisoendereodeumponteiro deveserguardadoemumponteiroparaponteiro. Exemplo4: cout << O valor de um_inteiro : << *ponteiro_para_int;
14
CaptuloIEngenhariadeSoftwareEstruturada
15
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
pointer = new double; pointer = i * 3.14159; delete pointer; } 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.
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]; cout << pointer[2];
16
CaptuloIEngenhariadeSoftwareEstruturada Oexemploacimaexibir 30comosada.Poderamos fazer aatribuio pointer = &array[0];da seguinteforma:Pointer = array;poisonomedoarrayfuncionacomoumponteiroparaasuaprimeira posio.Observeque,emborapossamosutilizaronomedeumarraycomoponteiro,nopodemosfazer coisasdotipo:array=&array2[0];Portanto,devemosconsiderararrayscomoponteirosconstantes.
Aritmtica de ponteiros
Comosabemos,osponteirossovariveisqueguardamendereosdememria.Porseremvaloresinteiros, podemos utilizar operaes aritmticas com ponteiros. A diferena que, se executarmos a instruo: um_inteiro++;avarivelum_inteiroser acrescidade1.Seexecutarmos:pointer++;avarivelpointerser acrescidadeumnmeroigualaotamanhodotipodepointer,ouseja,sepointerforumponteiroparaint,seu valorseracrescidode4(uminteirotemgeralmente4bytes),deformaque,sepointerestiverapontandopara umaseqnciadeinteiros,pointer++farcomqueeleaponteparaoprximoelemento.Parailustrarmelhora aritmticacomponteiros,segueumexemplo: int *pointer, array[10]; pointer = array; for (int i=0; i<10; i++) { *pointer = i*2; pointer++; } 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: const int *pointer; Istonosignificaqueoponteiros poder apontarparaconstantes.Narealidadeoqueestamosfazendo informandoaocompiladorqueeledevetratarovalorparaoqualoponteiroapontacomoumaconstante,e qualquer tentativa de tratlo de forma diferente causar erro de compilao. A importncia de utilizar ponteirosdestaforma,nosprevenirmosdeerrosqueocorreriamseovalorfosseinadvertidamentealterado.
17
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Outromotivo ques ponteirosparaconstantespodemapontarparaconstantes,osponteirosnormaisno (istoumtantoquantobvio). Apalavrachave const tambmpodeserutilizadaparadeclararponteirosconstantes(noteadiferenade ponteirosparaconstantes).Comoeradeseesperarponteirosconstantesspoderoapontarparaumendereo dememriaconstante,ouseja,nopodemalteraroendereocontidonele.Exemplo: int um_inteiro; int *const pointer = &um_inteiro; Portanto,comovoc j devedesconfiar,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: int add(int numero_1, int numero_2) { int numero_3; numero_3 = numero_1 + numero_2; return numero_3; } Claroqueasfunesquenscriamossogeralmenteumpoucomaiscomplexas,masesteexemploilustra bemoselementosdadefiniodeumafuno. Em C++, alm de definirmos umafuno (com todos os seus elementos), devemos tambm declarar as funesquedefinimos.Estadeclarao chamadadeprottipodeumafuno.Oprottipodeumafuno nadamaisdoqueaprimeiralinhadadefiniodafunoseguidadeumpontoevrgula.Ex:
18
CaptuloIEngenhariadeSoftwareEstruturada
19
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
{ int *retorno = new int[num_elementos]; for (int i=0; i<num_elementos; i++) { retorno[i] = 0; } return retorno;
Devemosobservarosseguintesaspectosnotrechodecdigoacima: Otipoderetornodafuno narealidadeumponteiro,comoj foiexplicadoantes.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; }; void function(structure uma_estrutura) { cout << Exibindo o nmero: <<uma_estrutura.um_inteiro<<endl; cout << Exibindo o char: << uma_estrutura.um_char << endl; } Napassagemdeparmetrosporvalor,oqueacontece queaestruturapassada copiadaparaumavarivel 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
Funes in-line
Quandofazemosumachamaaumafuno,ofluxodoprogramadesviadoparaoendereodafuno,seus argumentossocolocadosnapilha,entreoutrascoisas.Istogeraumoverheadnaexecuodeumprograma. Parasituaescrticas,oufunesbastantepequenas(comumaouduasinstrues),C++nospermitecriar funesinline.Nolugardaschamadasaestasfunes,ocompiladorcolocatodoocdigodafuno,de formaquenenhumdesvionecessrio.Adefiniodeumafunoinlinefeitacomapalavrachaveinline: inline int dobro(int num) { return 2*num; } Destaforma,todavezquefizermosumachamada funo dobro,ocdigo:2*numser colocadoemseu 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,estamosespecificandoumvalorqueser utilizadocasono seja fornecido nenhum valor para o argumento. Para definir um argumento padro para uma funo, utilizamosoigual,=,seguidopelovalor_padro,nadefiniodoprottipodafuno: int sum(int num1, int num2 = 1); int sum(int num1, int num2) { return num1+num2; } result = sum(10); Nocdigoacima,comonum2foideclaradocomvalorpadroiguala1,semprequefizermosumachamadaa sumsemosegundoargumento,ovalor1ser utilizadonoseulugar.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; } int sum(int num_elementos ...) { int resultado = 0, numero; va_list lista; va_start(lista, num_elementos); for(int i = 0; i < num_elementos; i++) { numero = va_arg(lista, int);
22
Nesteexemplo,afunosumrecebeumargumentoobrigatrio,que aquantidadedeargumentosvariveis 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 sum(int &num1, int num2); char *sum(char *str1, const char *str2); int main() { int num1= 10, num2 = 15, num3 = 20; char const *str1 = "World!"; char str2[20] = "great "; char str3[20] = "Hello "; cout cout cout cout cout cout cout cout cout cout << << << << << << << << << << "--- Funcao sum com inteiros ---" << endl; "soma total: " << sum(num3, sum(num2, num1)) << endl; "num1: " << num1 << endl; "num2: " << num2 << endl; "num3: " << num3 << endl << endl; "--- Funcao sum com strings ---" << endl; "Strings: " << sum(str3, sum(str2, str1)) << endl; "str1: " << str1 << endl; "str2: " << str2 << endl; "str3: " << str3 << endl;
cin.get(); return 0; } int sum(int &num1, int num2) { return (num1 = num1 + num2); } char *sum(char *str1, const char *str2) { return strcat(str1, str2); } 23
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
24
CaptuloIEngenhariadeSoftwareEstruturada
Abaixoseguemasseqnciasdecaracteresdeescapequemodificamoestadodatela,seenviadasparacout (ESCsignificaocaracteredeescape,cujocdigoascii27): Funo Normal Bold Blink (piscando) Reverso (cores do texto e fundo trocadas) Mover para a posio 0,0 Mover para a posio x,y Apagaratela Mudaracorparaatr,fg,bg(atr=0(normal)ou atr=1(highlight),fg=texto,bg=fundo) Seqnciadecaracteres ESC[0m ESC[1m ESC[5m ESC[7m ESC[f ESC[f ESC[yB ESC[xC ESC[fESC[2J ESC[atr;fg;bgm
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Cor Preto Vermelho Verde Marrom Azul Magenta Ciano Cinzaclaro Cinzaescuro Vermelhoclaro Verdeclaro Amarelo Azulclaro Magentaclaro Cianoclaro Branco
Valordeatr 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
Valordefg 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37
Valordebg 40 41 42 43 44 45 46 47
26
Captulo II
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
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: Um mdulo possui uma srie de operaes (funes) e um estado (variveis), que guarda o efeito das operaes. Possui tambm uma interface: conjunto de dados e operaes que esto disponveis aos outros mdulos; e uma implementao: definio das estruturas de dados e do corpo das funes. Esta definio de mdulo o que chamamos de estrutura de dados abstrata.
Informationhiddingumconceitodeengenhariadesoftwarequeconsisteemencapsularosdadosdeum mdulodeformaqueestesssejamacessveisatravsdainterfacedomdulo. 28
CaptuloIIEngenhariadeSoftwareBaseadaemObjetos Asinterfacesdosmdulossocriadasemarquivos.h.C++permiteacriaodeespaosdenomesseparados paracadamdulo,paraquenosecorraoriscodeexistirconflitoentrenomesdedadosoufunesiguaisem mdulosdiferentes.Istofeitoutilizandoseapalavrachavenamespace. Comovimosanteriormente,podemosutilizaraspalavraschave externestaticparadefiniraligao(externa ouinterna)dosdados.Veremosestesconceitosnaprticanaprximaseo. Organizao dos arquivos Abaixosegueummodelobsicodosarquivosdeummdulochamadomodulo1,comexplicaessobresuas partes: //----------------------------------------------------------------/* Arquivo modulo1.h */ #ifndef MODULO1_H #define MODULO1_H namespace modulo1 { // verifica se o arquivo j foi chamado // anteriormente para que no haja redefinio // do mdulo // indica que as definies abaixo pertencem ao // espao de nomes do modulo1
// definio das funes e estruturas de dados da interface // do mdulo extern void printResults(); extern int funcao1(int num1, int num2); extern char *str1; } #endif /* fim de modulo1.h */ //----------------------------------------------------------------/* Arquivo modulo1.cpp */ #include modulo1.h namespace modulo1 { // inclui a interface do modulo 1
// 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
cout <<"Imprimindo str1 do modulo 1: "<< str1 << endl; } // funcao privada static int funcao1(int num1, int num2) { return num1+num2; } } /* fim do arquivo modulo1.cpp */ //----------------------------------------------------------------Tipos abstratos de dados Neste captulo, aprendemos conceitos importantes da Engenharia de Software baseada em objetos. A modularizaodeumprogramatrazdiversasvantagens,poispermiteadivisodetarefas,tornamaisfcila implementaoepermitetestesmaisespecficos.Masoquefazersenecessitarmosdemaisdeumainstncia deummodulo?Umasoluoseriacopiarecolarosmdulosemarquivosdiferentes,tantasvezesquantas foremnecessrias,masistovaideencontroaosprincpiosdaextensibilidadeereusabilidade.Nocaptulo anterior,vimoscomocriartiposdedadoscompostos,estruturaseunies.Comoumaestruturaumnovotipo dedado,podemostervriasinstnciasdeumaestrutura.Acombinaodadivisodoprogramaemmdulos com arepresentao dos dados domduloatravs deestruturas oquechamamos de Tipos deDados Abstratos(ADTAbstractDataType). Almdasregrasaseremseguidasparaconstruodemduloseestruturas,aconstruodeumADTdeve levaremcontaasseguintesfuncionalidades: Construo:deveserpossvelalocareinicializarnovasinstnciasdoADT. Atribuio:devemospodercopiarosdadosdeumainstnciaparaoutra. Comparao:deveserpossvelcompararduasinstnciasdeumADT(ateno sdiferenasentre identidadeeigualdade) Manipulaodosdados:devemospodermanipularosdadosdeumADTsemsepreocuparcoma formadearmazenamentointerno,deformaaencapsularoADT. Destruio:devemosterapossibilidadedeliberaramemriaalocadaporumADT,quandono formosmaisutilizlo.
AodefinirmosumADTtendoemmenteestasresponsabilidadesestaremosimplicitamenteaplicandotodosos conceitosdeengenhariadesoftwarequeaprendemosatagora.
30
CaptuloIIEngenhariadeSoftwareBaseadaemObjetos float num2 = 12.34; double num3 = 56.7890; add(num1); add(num2); add(num3); cout << num1: << num1 << endl; cout << num2: << num2 << endl; cout << num3: << num3 << endl; cin.get(); } return 0;
template <typename T> void add(T &num) { num++; } Comopodemosperceber,ocompiladorseencarregoudegerarafunoparacadatipodedado.Masoque ocorreriaseutilizssemosumtipoparaoqualafunono adequada?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
Devemos definir as interfaces de cada mdulo antes de comear a implementlos. Faa diagramas representandoasrelaesentreosmdulosparaajudlo.Osmdulosdevemserimplementadosseguindoos princpiosdeumADT.
32
Captulo III
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Classes em C++
Vamosiniciaronossoaprendizadopartindodeumaestrutura.Damesmaformaqueadicionamosvariveis, podemosadicionarfunesaumaestrutura: struct TBall { int x, y; TColor color; int radius; void move(int x_step, int y_step) { x += x_step; y += y_step; }
};
Portanto,aestruturaTBallagorapossuiumafunomembro.Istosignificaqueafunopertenceestrutura es podeserchamadaapartirdela.Tambmpodemosobservarqueosmembrosdaestruturasovisveis dentrodafunomembro.Paratransformarestaestruturaemumaclasse,asnicascoisasquedevemosfazer so:substituirstructporclasseadicionarapalavrachavepublic:paraindicarquepodemosacessar osmembrosdaclasse: class TBall { public: int x, y; TColor color; int radius; void move(int x_step, int y_step) { x += x_step; y += y_step; }
};
34
Portanto,umavezvistocomodefinirumaclasse,eisumexemplodaclasse TBallcomtodososrequisitos 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; public: // Todos os mtodos de manipulao de atributos, os // construtores e o destrutor devem ser pblicos. // // // // // // Construtores da classe TBall, servem para alocar memria e inicializar os objetos da classe. Os construtores so mtodos que devem possuir o mesmo nome da classe e so chamados sempre que um novo objeto da classe criado. Abaixo temos dois construtores para a classe:
// Construtor 1: no possui parmetros, inicializando os // atributos com valores padro. TBall () { x = 0; y = 0; color = clBlack; radius = 1; } // Construtor 2: permite que os atributos sejam inicializados // com os valores desejados. TBall (int x1, int y1, TColor c, int r) { x = x1; y = y1; color = c; radius = r; } // Destrutor da classe TBall. Deve possuir o mesmo nome da // classe precedido de um ~. chamado toda vez que um // objeto destrudo (com o operador delete). // No seu corpo geralmente existem instrues para desalocar as // variveis criadas dinamicamente. Como no existem atributos // desta forma, o corpo do destrutor est vazio e sua // declarao poderia ser omitida. Foi exibida aqui a ttulo de // exemplo de destrutor. ~TBall{} // Alm dos construtores e do destrutor, devemos fornecer 35
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
// mtodos pblicos para manipular os atributos da classe. void move(int x_step, int y_step) { x += x_step; y += y_step; } 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.Comoodestrutor chamadopelaestruturainternadoprograma,quandoumobjetosaido escopoouquandoutilizamosooperadordelete,umdestrutornopossuiparmetros.
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*/ void TBall::move(int x_step, int y_step) // corpo do mtodo { x += x_step; y += y_step; } . . . /* fim de 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.Umaoutraformadecriarmtodosinlineutilizandoapalavraclave inline,comoveremosa seguir: inline void TBall::setColor(TColor c) { color = c; } Adeclaraodomtodonadefiniodaclassecontinuasendofeitadamesmaforma. Mtodos constantes
37
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Sedeclararmos umobjetodeumaclassecomoconstante,comousode const,s poderemoschamaros mtodosdoobjetoqueforemconstantestambm,ouseja,ummtodoserchamadoconstantesignificaqueo mtodonoalterar osatributosdoobjeto.Osmtodosconstantestambmsodeclaradoscomapalavra chaveconstcolocadaapsalistadeargumentosdomtodo: TColor TBall::getColor() const { return color; }
O ponteiro this
TodaclasseemC++possuiumponteiroespecialchamadothis,queapontaparaainstanciaatualdoobjeto. Porexemplo,secriarmosummtodoquenecessiteretornaroprprioobjeto,podemosutilizarthisparaisto. Ex: class TBall { TBall & compare(const TBall &ball); . .
38
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses . }; TBall & TBall::compare(const TBall &ball) { if (radius >= ball.radius) return *this; else return ball; } int main () { TBall ball1(10, 20, clWhite, 30); TBall ball2(30, 100, clBlack, 10); cout << A bola maior a << ball1.compare(ball2).getColor.getName() << endl; } return 0;
Asadadoprogramaser: A bola maior a branca Podemosperceber,nesteexemplo,quepassamoseretornamosoobjeto TBallporreferncia.Porqueisto feito?VocdevelembrarqueoC++,aopassarumestruturaparaumafuno,passaaporvalor,fazendouma cpiadaestruturana readearmazenamentoautomtico.Comobjetosaconteceomesmo.Paraevitareste overhead da cpia, os parmetros so passados por referncia, e, quando no sero alterados dentro do mtodo,sopassadoscomorefernciaconstante.
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); . . . }; TPlayer::TPlayer(char *str, int scr) { name = new char[strlen(str)+1]; strcpy(name, str); score = scr; } TPlayer::TPlayer(const TPlayer & player) { name = new char[strlen(player.name)+1]; strcpy(name, player.name); score = player.score; } Usarconstrutoresdecpiadevesetornarumhbitodaquiparafrente,principalmentesetivermosobjetosque armazenemponteiros.
40
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses cout << Nome: << player.name << endl; cout << Score: << player.score << endl;
Devemosutilizarasfunes friend combastantecuidado,poisseuusoindevidopodecausarumfurono conceitode informtionhidding.Nasprximasseesveremosmaisalgunsmotivosparacriarmosfunes friend. Almdepodercriarfunesfriend,podemoscriarmtodoseclassesfriend.Veremosistonasseesaseguir. Criando mtodos friend Acriaodeummtodofriend anlogadeumafunofriend,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); . . . }; void TScreen::display(const TPlayer & player) { cout << Nome: << player.name << endl; cout << Score: << player.score << endl; } NotequetivemosquedeclararaclasseTPlayer (vejaaprimeiralinhadoexemplo)antesdeutilizlano mtododisplaydeTScreen.NopodamossimplesmentetercolocadoaclasseTPlayerantespoisela declaraomtododisplaydeTScreencomofriend,eocompiladorreclamariaqueaindanoviua classeTScreen. Criando classes friend 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); }; void TScreen::display(const TPlayer & player) { cout << Nome: << player.name << endl; cout << Score: << player.score << endl; }
42
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses private: int x, y; TColor color; int radius; public: operator int() const; . . .
};
TBall::operator int() const { return radius; } Assim,ocdigoabaixotambmfuncionarcorretamente: TBall ball1(10, 20, clBlack, 30); int raio; raio = ball1;
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>>. Asobrecargadeoperadores semelhante sobrecargademtodos,adiferena queutilizamosapalavra chave operator para indicar que estamos sobrecarregando um operador. Nas sees seguintes, veremos algumaspeculiaridadesdasobrecargadeoperadoresquenecessitamdeumaatenoamais. Sobrecarregando operadores unrios, como ++ e -Parasobrecarregarumoperadorunrio,devemoscriarummtodonaclassecomaseguintesintaxe: tipo operatorop() { } Ondetipo,otipoderetornodooperador,quenestecasoonomedaclassee opooperadoremsi,como+ +ou. Portanto,parasobrecarregarooperador++daclasseTBallqueincrementaoraiodabola,procedemosda seguinteforma: 43
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
class TBall { private: int x, y; TColor color; int radius; public: TBall & operator++(); . . . }; TBall & TBall::operator++() { radius++; return (*this); } Devemosobservarqueestecdigos sobrecarregaooperador++prfixado.Parasobrecarregarooperador psfixado,utilizamos: TBall operator++(int); Ondeoargumentointdiferenciaosoperadores. Sobrecarregando operadores binrios, como + e 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); . . . }; TBall TBall::operator+(const TBall &ball) { TBall retBall(0, 0, clBlack, 0); retBall.x = ball1.x + ball2.x; retBall.y = ball1.y + ball2.y;
44
Notequecriamosumnovoobjetodentrodocorpodooperadoreretornamosesteobjeto(narealidadeuma cpiadesteobjeto). Masoqueaconteceriasedesejssemosfazercoisasdotipo:ball = ball + 2ouball = 2 + ball? Comonasegundaexpresso,ooperandono umobjeto,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; } TBall operator+(const TBall &ball1, const TBall &ball2) { TBall retBall(0, 0, clBlack, 0); retBall.x = ball1.x + ball2.x; retBall.y = ball1.y + ball2.y; retBall.radius = ball1.radius + ball2.radius; return retBall; } DevemosnotarquecriamosumconstrutordeconversodeintparaTBall,demodoestasoluoatendea todasasexpressesvistasanteriormente.Esteumdosprincipaismotivosdousodefunesfriend. Sobrecarregando os operadores >> e << C++permitesobrecarregarosoperadoresdeinseroeextraodefluxo:>>e<<.Parasobrecarregarestes operadores,devemospassarcomoparmetroeretornarofluxocorrespondente(ostreamouistream),para queestesoperadorespossamserencadeados. padrotornarestesoperadores frienddaclasseparaoqual estsendosobrecarregado.Vejamosasintaxedasobrecargadesteoperador: friend ostream & operator<<(ostream &stream, const tipo_classe &c); friend istream & operator>>(istream &stream, const tipo_classe &c); 45
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Sobrecarregando o operador [] Ooperador[],dendicedearray,tambmpodesersobrecarregado.Istonospermiteutilizar ndicesdearray comosobjetospararetornardadosdoarmazenamentointernodoobjeto.Parasobrecarregaresteoperador devemoscriarummtododaseguinteforma: tipo operator[](int index); 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: tipo_da_classe & operator=(const tipo_da_classe & objeto); Note que se passarmos o argumento por referncia, devemos retornar o objeto por referncia para que possamosencadearooperadorsucessivamente.
Modelos de classes
OC++permitecriarmodelosdeclasses(classtemplates)damesmaformaquecriamosmodelosdefuno, paradarumamaiorgeneralizaoaonossocdigo.Estesmodelosnospermitemusarummesmoalgoritmo paravriostiposdedados,evitandoreescreverumaclasseparacadatipo.Paracriarmodelosdeclasses, procedemosdeformaanlogacriaodemodelosdefuno: template <lista_de_parmetros> class nome_da_classe { . . . }; AbaixoveremosaclasseTStack,umapilhagenrica. template <typename T> class TStack { private: T element; TStack *next; 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(); }; template <typename T> TStack<T>::TStack() { next = NULL; } template <typename T> TStack<T>::TStack(const T &e) { element = e; next = NULL; } template <typename T> TStack<T>::TStack(const TStack &stack) { element = stack.element; if (stack.next != NULL) next = new TStack(stack.next); else next = new TStack();
template <typename T> TStack<T>::~TStack() { if (next != NULL) delete next; } template <typename T> T& TStack<T>::operator=( const TStack &stack) { element = stack.element; if (stack.next != NULL) next = new TStack(stack.next); else next = new TStack(); } return *this;
template <typename T> bool TStack<T>::isEmpty() { bool ret = false; if (next == NULL) ret = true; return ret; } template <typename T> void TStack<T>::push(const T &e) {
47
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
if (next != NULL) { next->push(e); } else { element = e; next = new TStack(); } } template <typename T> T TStack<T>::pop() { T e; 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,poistypename muito maisgenricodoqueclass. Osmodelosdeclassetambmpermitemmaisdeumtipodedadoscomoparmetrodomodelo.Oseguinte cdigomostracomodefinirummodelodeclassedependentededoistiposdedados: Template <typename T1, typename T2> Class nome_da_classe { . . . }; Note que os outros parmetros podem ser tipos de dados genricos (declarados com typename) como tambmtiposespecficos(charouint,porexemplo).
48
CaptuloIIIEngenhariadeSoftwareBaseadaemClasses
49
Captulo IV
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Herana em C++
VejamosumexemplodecomoutilizarheranaemC++.DefiniremosumaclassechamadaTShape.Apartir destaclasse,criaremosTBlock(bloco)eTBall(bola): class TShape { . . . }; class TBlock : public TShape { . . . }; class TBall : public TShape { . . . }; Comopodemosperceber,paracriarumaclassequeherdadeoutra,bastaapenasincluir: : modificador nome_superclasse apsonomedasubclasse.Omodificadorserveparaespecificarcomoasuperclasseser vistadentroda subclasse.Omodificadorpublicindicaqueosmembrospblicosdasuperclassecontinuamsendopblicosna subclasse. Analogamente, os modificadores protected e private tornam os membros da superclasse protegidosouprivadosnasubclasse.
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(); }; class TBlock : public TShape { private: char *pattern; public: TBlock(int x1, int y1, const char *pat); ~TBlock(); }; TShape::TShape(int x1, int y1, const char *n) { x = x1; y = y1; name = new char[strlen(n)+1]; strcpy(name, n); } TShape::~TShape() { delete[] name; } TBlock::TBlock(int x1, int y1, const char *pat) :TShape(x1, y1, block) { pattern = new char[strlen(pat)+1]; strcpy(pattern, pat); } TBlock::~TBlock() { delete[] pattern; } Note que utilizamos :TShape(x1, y1, block) para chamar o construtor da superclasse. Os construtoresdassuperclassessosemprechamadosantesdosconstrutoresdassubclasses.Comosdestrutores ocorreoinverso:osdestrutoresdassubclassessochamadosantesdosdassuperclasses. Asobreposiodemtodosocorredeformasemelhante,adiferena que,parachamarmosmtodosda superclassedentrodasubclasseutilizamos:nome_superclasse::metodo(parametros).
53
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Comojvimos,possveltermosponteirosparaobjetosdeumaclasse.OC++tambmpermitequeponteiros paraumasuperclasseapontemparaobjetosdeumaclassederivada,apesardenopoderacessarosmembros especficosdesta.Esteprocesso,deumponteiropoderapontarparadiversosobjetosderivadosdistintos chamadopolimorfismo.Entovoc deveestarpensando: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(); }; class TBlock : public TShape { private: char *pattern; public: TBlock(int x1, int y1, const char *pat); ~TBlock(); 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,oponteiroshapePtr dotipoTShapee,apesardepodermosapontarparaumobjetodo tipo TBlock (afinal um TBlock um TShape), ao chamarmos um mtodo atravs do ponteiro, o compiladorfar umaligaoesttica(staticbidingligaoemtempodecompilao)davarivelponteiro comomtododesuaclasse.IstofarcomqueomtododaclasseTShapesejachamadoindependentemente deparaqualobjetooponteiroaponte(afinal,emtempodecompilaono possvelsaberocontedodo ponteiro). Ento,comochamaramosomtodocorreto?OC++ofereceumaalternativaquepermitequealigaodo objetocomomtodosejafeitadinamicamente(dynamicbidingligaoemtempodeexecuo).Istofeito, declarandoomtododasuperclassecomo virtual.Quandodeclaramos ummtododestaforma,estamos avisandoaocompiladorparafazeraligaodoobjetocomomtodoemtempodeexecuo,paraqueo mtododoobjetocorretosejachamado.SenadeclaraodaclasseTShapedoexemploanterior,tivssemos aseguintelinha: virtual void draw(); 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,estaremosassegurandoqueodestrutorcorretoser chamadoquandoumobjetodeumaclasse derivadafordestrudo.
Classes abstratas
Umaclasse ditaabstrataquandopossuiumoumaismtodosquenoforamimplementados(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; }; class TBlock : public TShape { 55
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
public: . . . void draw(); }; void TBlock::draw() { cout << Drawing a block << endl; } class TBall : public TShape { public: . . . void draw(); }; void TBall::draw() { cout << Drawing a ball << endl; } class TBar : public TShape { public: . . . void draw(); }; void TBar::draw() { cout << Drawing a bar << endl; } Comovimos,todasasclassesderivadasdeTShapedeveroimplementaromtododraw().
Herana mltipla
OC++permitequeumaclasseherdedevriasoutras,incorporandoosmembrosdasduasclasses.Aherana mltipla contestadaporalgunsprogramadores,poisistofacilitaoconflitoentreosmembrosdasclasses. Vejamoscomodeclaramosumaclassecomheranamltipla: class TScreenObjects : public TBall, public TBar, public TBlock { . . . };
56
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos Portanto,aclasse TScreenObjects possuiosmembrosdetodasasclassesqueelaherda.Masoque acontecesechamarmosomtodo draw(),queexisteemtodasassuperclassesde TScreenObjects? Nestecaso,ocompiladorgerariaumerro,poisnosaberiadequeclassechamaromtodo.Umasoluoseria fazerumaheranaprivadadassuperclasses(deformaqueseusmembrosnoficassemvisveisapartirda subclasse)edefinirmtodosparachamaromtododraw()decadasuperclasse: class TScreenObjects : private TBall, private TBar, private TBlock { public: drawBall() { TBall::draw(); } drawBar() { TBar::draw(); } drawBlock() { TBlock::draw(); } }; Outroproblemaqueenfrentamoscomaheranamltipla que,quandocriamosumobjetodasubclasse, estamoscriandoumobjetointernodecadasuperclasse.Eseassuperclassesherdaremdeumamesmaclasse base?Serocriadosvriosobjetosinternosdaclassebase(notequeserocriadosvrios objetosinternos idnticos),equandochamarmosummtododestaclassebase,ocompiladornosaber dequaldosobjetos internoschamaromtodo.Pararesolveristo,asclassesdevemfazerumaheranavirtualdaclassebase,de formaqueumnicoobjetodaclassebasesercriado: class TBall : public virtual TShape { . . . }; class TBar : public virtual TShape { . . . }; class TBlock : public virtual TShape { . . . }; class TScreenObjects : private TBall, private TBar, private TBlock { . . . }; Usarheranavirtualeliminaoconflitodeusarmosclassesbasecompartilhadas.Maseseassuperclassesde TScreenObjectspossuremconstrutoresquepassemargumentosdistintosparaaclasseTShape?Como oprogramaspodecriarumobjetocompartilhadodaclasseTShape,oC++desativaapassagemautomtica deparmetros(cominicializadores)dasclassesintermediriasparaaclassebasevirtualenoseulugarchama oconstrutorpadrodestaclasse.Vejamosesteexemplo:
57
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
TScreenObjects(int x1, int y1, const char *pattern) : TBall(x1, y1, pattern), TBar(x1, y1, pattern), TBlock(x1, y1, pattern) {}; Nesteexemplo,osconstrutoresdasclassesTBall, TBar e TBlocknoteropermissoparapassaros argumentosparaaclasseTShape.Paraqueesteexemplofuncionecorretamente,devemoschamartambmo construtordaclasseTShape: TScreenObjects(int x1, int y1, const char *pattern) : TShape(x1, y1, screenObject), TBall(x1, y1, pattern), TBar(x1, y1, pattern), TBlock(x1, y1, pattern) {}; AssimgarantimosainicializaocorretadosobjetosdaclasseTScreenObjects.
Excees
Exceessoerrosdetempodeexecuo,ouseja,nosobugs(errosdalgicadoprograma),massimerros geradospelamanipulaodedadosinadequados(geralmentefornecidosporusurios).Vejamosumexemplo destetipodeerro: int main () { int num1, num2; cout << Digite dois nmeros: ; cin >> num1 >> num2; cout << A diviso do nmero << num1 << pelo nmero ; cout << num2 << << (num1/num2) << endl; return 0; } Nesteexemplo,apesardalgicaestarcorreta,poderamosterumerrodetempodeexecuo(runtimeerror) casoousurioinformasseovalorzeroparaosegundonmero. Paraestestiposdeproblema queexistemasexcees.Omecanismodeexcees nospermitetentar executar(try)umdeterminadocdigo,casoocdigonopossaserexecutadolanamos(throw)uma exceoquesercapturada(catch)etratadaemoutrapartedocdigo.Vejamoscomoistofunciona: int main () { int num1, num2; cout << Digite dois nmeros: ; cin >> num1 >> num2; try {
if (num2 == 0) { throw string(Erro: diviso por zero.); } cout << A diviso do nmero << num1 << pelo nmero ; cout << num2 << << (num1/num2) << endl;
58
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos } catch(string str) { cout << str << endl; } return 0; } Nocdigoacima,apartesensvel(ondepodeocorrerumaexceo), colocadadentrodeumblocotry. Casohajaumerro,lanamosumaexceocom throw,eofluxodoprogramaser desviadoparaforado bloco try.Apartirdestemomento,oprogramair procurarumbloco 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.Senafunomaintambmnohouverumbloco catchparaestetipodeexceo,o programaencerrado. Comovoc j deveterpercebido,podemoslanarumaexceodequalquertipodedado(inclusiveclasses especficasparatratamentodeexcees,comcdigoemensagensdeerro,etc..).OANSI/ISOC++define umaclassedeexceopadrochamada exception.Estaclassepossuiummtodoconstantechamado what()queretornaumconst char*contendoumamensagemdeerrodaexceo.Portanto,podemos criarnossasclassesdeexceoherdandodaclasse exceptionesobrescrevendoomtodowhat()para queexibaamensagemdeerroadequada.Vejamosumexemplo: class TDivideByZeroException : public exception { private: char *msg; public: const char *what() const {return msg;} TDivideByZeroException() {msg = Erro: diviso por zero.;} }; int main () { int num1, num2; cout << Digite dois nmeros: ; cin >> num1 >> num2; try { if (num2 == 0) { throw TDivideByZeroException(); } cout << A diviso do nmero << num1 << pelo nmero ; cout << num2 << << (num1/num2) << endl;
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;
60
CaptuloIVEngenhariadeSoftwareOrientadaaObjetos
TBall
TBar
TBlock
Podemos,pensandoanalogamente,verificartodoonossoprogramaembuscadegruposdeclassesquepodem sergeneralizadas,aumentandoareusabilidadedonossocdigo.
61
Captulo V
CaptuloVRecursosavanadosdoC++:RTTIeSTL
NotequeparautilizaroselementosdaRTTIdeC++necessrioincluiroarquivodecabealhotypeinfo.
O operador dynamic_cast
Esteoperador utilizadoquandonecessitamosconverterumponteirodeumaclassebaseparaumaclasse derivada,parapoderutilizarosmembrosdaclassederivada.Istos possvel,seoponteirodaclassebase estiverapontandoparaumobjetodaclassederivada.Senoforocaso,ooperadorretornaNULL(ponteiro nulo).Vejamosumexemplo: int main() { TBall bola; TShape *shapePtr = &bola; TBall *ballPtr = NULL; ballPtr = dynamic_cast <TBall *> (shapePtr); if (ballPtr != NULL) { cout << cast realizado com suceso! << endl; } else { cout << no foi possvel realizar o cast! << endl; } return 0;
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; } cout << o tipo do objeto apontado por shapePtr ; cout << typeid(*shapePtr).name() << 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
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.Umiterator umageneralizaopara 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
Representaumarrayunidimensional.Aprincipalvantagemdeutilizareste continer,emvezdeumarray,quepodemosalteraroseutamanhofacilmente emtempodeexecuo. vector 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 reverse_iterator rend (); const_reverse_iterator rend () const; // Capacidade size_type size () const; size_type max_size () const; void resize (size_type); void resize (size_type, T); size_type capacity () const; bool empty () const; voidreserve(size_type); // Acesso aos elementos referenceoperator[](size_type); const_referenceoperator[](size_type)const; referenceat(size_type); const_referenceat(size_type)const; referencefront(); const_referencefront()const; referenceback(); const_referenceback()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
Arquivodecabealho Interface
Representaumalistaduplamenteencadeada.Devemosutilizarestecontiner quandonecessitamosdefreqentesinsereseremoesnomeiodalista,pois estecontinerofereceumtempodeacessoconstanteaoselementos,independente dotamanhodalista. list 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); // Acesso aos elementos referencefront(); const_referencefront()const; referenceback(); const_referenceback()const; // Modificadores voidpush_front(constT&); voidpop_front(); voidpush_back(constT&); voidpop_back();
68
CaptuloVRecursosavanadosdoC++:RTTIeSTL iterator insert (iterator, const T&); void insert (iterator, size_type, constT&); template<classInputIterator> voidinsert(iterator,InputIterator, InputIterator); iteratorerase(iterator); iteratorerase(iterator,iterator); voidswap(list<T,Allocator>&); voidclear(); // 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
Arquivodecabealho Interface
Doinglsdoubleendedqueue,representaumafilacomdoisfinais,ouseja, podemosadicionarouremoverelementosemambasasextremidades.Possui operaesdeinseroeapagamentocomtempoconstanteparaoincioefinalda fila,masotempodeacessocrescelinearmentecomotamanhodafilaparaacessos aelementosdomeio. deque 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; // Acesso aos elementos referenceoperator[](size_type); const_referenceoperator[](size_type)const; referenceat(size_type); const_referenceat(size_type)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(); };
Representaumafilaemquepodemosfazerinseresnoincioeremover elementosdofim.umaformarestritadocontinerdeque. Queue 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
Arquivodecabealho Interface
Representaumafiladeprioridade.Aordemdoselementosdeterminadapelo operadormenorque,<oupelocomparadorcompare.Istosignificaqueos objetosguardadosnestecontinerdevemteresteoperadorsobrecarregadoalmde umconstrutordecpia,destrutoreoperador=. queue 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(); };
Representaumapilha,comoperaesparaempilhar,desempilhareverotopoda pilha. stack 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(); };
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
size_type erase (const key_type&); void erase (iterator, iterator); void swap (set<Key, Compare, Allocator>&); void clear (); // Observao de elementos key_compare key_comp () const; value_compare value_comp () const; // Operaes sobre conjuntos size_type count (const key_type&) const; pair<iterator,iterator>equal_range(constkey_type&) const; iteratorfind(constkey_type&)const; iteratorlower_bound(constkey_type&)const; iteratorupper_bound(constkey_type&)const; };
Ocontinermultisetrepresentaumconjunto(semelhanteaoset)emqueos elementosnoprecisamsernicos. set 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 const Compare& = Compare(), const Allocator& = Allocator()); multiset (const multiset<Key, Compare, Allocator>&); ~multiset (); multiset<Key, Compare, Allocator>& operator= (constmultiset<Key, Compare,Allocator>&); // 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; // Operaes sobre Multiset iteratorfind(constkey_type&)const; size_typecount(constkey_type&)const; iteratorlower_bound(constkey_type&)const; iteratorupper_bound(constkey_type&)const; pair<iterator,iterator>equal_range (constkey_type&)const; };
75
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
class Allocator = allocator<pair<constKey, T>>> classmap { public: // 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; };
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 const_reverse_iterator rend () const; // 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; // Operaes sobre Multimap iteratorfind(constkey_type&); const_iteratorfind(constkey_type&)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; };
Estecontinerrepresentaumconjuntodebits(bitset),quepodemseracessados individualmentecomooperadorcolchetes,[].Ofereceoperaeslgicasbitabit bemcomomtodosdemanipulaodosbitsindividualmenteouemconjunto. bitset 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); // Set, Reset, Flip bitset<N>&set(); bitset<N>&set(size_t,int=1); bitset<N>&reset(); bitset<N>&reset(size_t); bitset<N>operator~()const; bitset<N>&flip(); bitset<N>&flip(size_t); // Acesso aos elementos referenceoperator[](size_t); unsignedlongto_ulong()const; template<classcharT,classtraits,classAllocator> basic_string<charT,traits,Allocator> to_string(); size_tcount()const; size_tsize()const; booloperator==(constbitset<N>&)const; booloperator!=(constbitset<N>&)const; booltest(size_t)const; boolany()const; boolnone()const; bitset<N>operator<<(size_t)const; bitset<N>operator>>(size_t)const; }; // 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 template <size_t N> bitset<N> operator^ (constbitset<N>&,constbitset<N>&); template<size_tN>istream& operator>>(istream&,bitset<N>&); template<size_tN>ostream& operator<<(ostream&,constbitset<N>&); 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(); } A classe template valarray Aclassevalarrayummodelodeclasseprojetadoparaserutilizadocomvaloresnumricos.Semelhanteao continervector,valarrayotimizadaparapermitiraplicaroperaesefunesmatemticasaoarray,como mximodeeficincia.Vejamosumexemplodeuso: int main() { valarray<int> array1(10); valarray<int> array2(10); for(int i = 0; i<10; i++) { array1[i] = i; } array2 = array1 + 10; // soma 10 a cada elemento de array1 e // atribui a array2 array1 += array2; // soma cada elemento de array1 com array2
81
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
Iteradores
ASTLdeC++possuiumconjuntodeponteirosgenricosutilizadosparamanipularosdadosdoscontiners. Damesmaformaqueousodecontineresnospermiteutilizarosalgoritmosindependentedotipodedados, ositeradoresgeneralizamousodosalgoritmos,independentedocontiner.Ousodeiteradoressemelhante aousodeponteirosdeformaqueocdigoabaixo: int nums[10]; int *ptr; for (int i=0, ptr = nums; ptr != nums+10; i++, ptr++) *ptr = i; Podeserescritodestaforma: vector<int> nums(10); vector<int>::iterator itr; for (int i=0, itr = nums.begin(); itr != nums.end(); i++, itr++) *itr = i; 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 Arquivodecabealho Interface acumulavaloresdeoperaesmatemticassucessivas. numeric template <classInputIterator,classT> Taccumulate(InputIteratorfirst, InputIteratorlast, Tinit);
82
Copiadadosentrecontineres. algorithm template<classInputIterator,classOutputIterator> OutputIteratorcopy(InputIteratorfirst, InputIteratorlast, OutputIteratorresult); template<classBidirectionalIterator1, classBidirectionalIterator2> BidirectionalIterator2 copy_backward(BidirectionalIterator1first, BidirectionalIterator1last, BidirectionalIterator2result);
Contaonmerodeelementosdeumcontiner.Oalgoritmocount_ifcontaos elementosdocontinerquesatisfazemumpredicado. algorithm 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);
83
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate binary_pred); find Descrio Arquivodecabealho Interface
min_element e max_element Descrio Retornamumiteradorqueapontaparaomnimoeomximoelementodo continer,respectivamente. algorithm Arquivodecabealho template<classForwardIterator>ForwardIterator Interface 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);
Embaralhaaleatoriamenteoselementosdentrodointervalodeitaradoresfirste last,comdistribuiouniforme.Poderecebercomoargumentoumobjetofuno quegerenmerosaleatriosparaalteraradistribuio. algorithm template<classRandomAccessIterator> voidrandom_shuffle(RandomAccessIteratorfirst, RandomAccessIteratorlast); template<classRandomAccessIterator, classRandomNumberGenerator> voidrandom_shuffle(RandomAccessIteratorfirst, RandomAccessIteratorlast, RandomNumberGenerator&rand);
84
CaptuloVRecursosavanadosdoC++:RTTIeSTL
Rotacionaoselementosdosegmentoquevaidefirstatmiddle1comos elementosdosegmentodemiddleatlast.Oalgoritmorotate_copyretorna umacpiadocontinerrotacionado. algorithm template<classForwardIterator> voidrotate(ForwardIteratorfirst, ForwardIteratormiddle, ForwardIteratorlast); template<classForwardIterator,classOutputIterator> OutputIteratorrotate_copy(ForwardIteratorfirst, ForwardIteratormiddle, ForwardIteratorlast, OutputIteratorresult);
search Descrio
Arquivodecabealho Interface
85
DoCaoC++:umaabordagemdaEngenhariadeSoftware
TiagoBarros
ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template <classForwardIterator1, classForwardIterator2, classBinaryPredicate> ForwardIterator1search(ForwardIterator1first1, ForwardIterator1last1, 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)
Ordenaoselementosdeumcontiner.Paracomparaoentreoselementosdo continer,podeserutilizadoooperadormenorque,<,ouumobjetofuno compare. algorithm 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. algorithm Arquivodecabealho template<classT>voidswap(T&a,T&b); Interface template<classForwardIterator1, classForwardIterator2> ForwardIterator2swap_ranges(ForwardIterator1first1, ForwardIterator1last1, ForwardIterator2first2);
transform Descrio
Aplicaumafunoaumintervalodevaloresdeumcontiner.
86
CaptuloVRecursosavanadosdoC++:RTTIeSTL
Arquivodecabealho Interface
algorithm 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. algorithm Arquivodecabealho template<classForwardIterator>ForwardIterator Interface 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 + * / % - (unrio) == != > < >= <= && || ! Objetofunocorrespondente plus minus multiplies divides modulus negate equal_to not_equal_to greater less greater_equal less_equal logical_and logical_or logical_not
88