You are on page 1of 69

Entendendo C++

Do original: Understanding C++: An Accelerated Introduction by Marshall Brain


http://www.arnaut.eti.br/op/CPPAI00.htm!C"!#Dndice
O objetivo dessa srie de tutoriais ajud-lo a compreender os conceitos fundamentais
da linguagem C++ de um modo rpido e indolor. Inicialmente voc ser levado a pensar
de modo orientado a ob$eto. Uma vez ue compreenda esses fundamentos! o restante
da linguagem ser entendido de um modo relativamente fcil! porue voc ter uma base
" ual poder acrescentar novos conceitos! na medida em ue necessite deles. Uma vez
ue voc ten#a compreendido os temas principais e o vocabulrio! C++ se tornar
tambm para voc uma linguagem e$traordinria e poderosa. Usada corretamente! C++
pode mel#orar dramaticamente sua produtividade como programador.
Os tutoriais come%am com uma breve e$plana%&o sobre porue C++ e$iste e a ue se
destina. C++ uma resposta a in'meros problemas ue surgem em programa%&o de
grandes projetos! e as caracter(sticas da linguagem fazem mais sentido se voc as ol#ar
desse ponto de vista. ) se%&o seguinte descreve os recursos espec(ficos do C++ ue se
sobrep*em e corrigem deficincias da linguagem C. O restante dos tutoriais apresenta os
conceitos de programa%&o orientada a objeto! e os modos como C++ materializa esses
conceitos.
%ota sobre compiladores:
&e 'oc( )uer aprender programa*+o em C++, 'oc( precisa ter um compilador. &e
'oc( n+o tem algumas centenas de d-lares para gastar na compra de um
compilador comercial como .isual C++, /orland ou 0atcom, ent+o 'oc( pode usar
um dos compiladores gratuitos dispon1'eis na 0E/. Um desses compiladores est2
dispon1'el em http://www.delorie.com/d$gpp/
3ndice
04 Introdu%&o
05 +$tens*es ao C
0" ,ocabulrio C++
06 Classes
07 -eran%a
08 .obrecarga de Operador
09 /rabal#ando com 0ointers
0# 1un%*es ,irtuais
Os tutoriais 2 e 3 entram mais profundamente em detal#es sobre pointers. .e voc ainda
n&o se sente " vontade para tratar de pointers! salte-os e leia o /utorial 4
Introdu*+o
0ara muitos a transi%&o de C para C++ n&o fcil. 5e fato! essa transi%&o
freuentemente acompan#ada de muita ansiedade porue C++ popularmente envolto
Pg: 1 de 69.
em uma aura de inacessibilidade. 0or e$emplo! voc pode pegar um livro sobre C++! abri-
lo em uma pgina ualuer e deparar-se com um pargrafo mais ou menos assim6
Do ponto de 'ista de pro$eto, deri'a*+o pri'ada : e)ui'alente a compartimenta*+o,
e;ceto pela, ocasionalmente importante, )uest+o de sobreposi*+o. Um uso
importante disso : a t:cnica de deri'ar uma classe publicamente a partir de uma
classe base abstrata, de<inindo uma inter<ace, e pri'ati'amente de uma classe
concreta pro'endo uma implementa*+o. Por)ue a heran*a impl1cita na deri'a*+o
pri'ada : um detalhe de implementa*+o )ue n+o : re<letido no tipo da classe
deri'ada, ela : algumas 'e=es denominada >heran*a de implementa*+o> e contrasta
com a declara*+o p?blica, onde a inter<ace da classe base : herdada e a con'ers+o
impl1cita para o tipo da classe : permitida. @ restante : algumas 'e=es re<erido
como uma a subAtipi<ica*+o ou >heran*a de inter<ace7. 8/rec#o e$tra(do de 7/#e C++
0rogramming 9anguage! second edition! b: ;jarne .troustrup! page <=>?
@ realmente dif(cil iniciar-se em C++ com uma literatura assim t&o rebuscada! t&o
#ermtica.
+ssa srie de tutoriais respondem a trs uest*es bastante comuns6
0orue C++ e$iste e uais s&o suas vantagens sobre o CA
Bue recursos est&o dispon(veis no C++ para materializar ideias orientadas a
objetoA
Como voc projeta e implementa cCdigo usando os princ(pios da orienta%&o a
objetoA
Uma vez ue voc ten#a compreendido os recursos bsicos dispon(veis no C++! e saiba
como e porue us-los! voc se tornar um programador em C++. +ssas srie de tutoriais
v&o inici-lo nessa dire%&o! e tornar outros te$tos sobre C++! inclusive os de .troustrup!
mais fceis de entender.
+sses tutoriais presumem ue voc con#ece a linguagem C. .e esse n&o o seu caso!
gaste uma semana ou duas aprendendo C e ent&o retorne a esses tutoriais. C++ um
superset do C! portanto uase tudo ue voc souber sobre C vai encontrar cone$&o
nessa nova linguagem.
Por)ue C++ e;isteB
)s pessoas ue s&o novatas em C++! ou aueles ue leem livros sobre C++! geralmente
tem duas perguntas6
7/udo o ue leio tem um vocabulrio maluco6 encapsulamento! #eran%a! fun%*es
virtuais! classes! sobrecarga! amigos... 5e onde vem tudo issoA
+ssa linguagem - e programa%&o orientada a objeto de um modo geral -
obviamente implicam em uma mudan%a de mentalidade! ent&o como eu fa%o para
aprender a pensar em modo C++A
)mbas essas uest*es podem ser respondidas! e o projeto do C++ como um todo
facilmente intelig(vel! se voc souber o ue os projetistas do C++ pretendiam atingir
uando criaram essa linguagem. .e voc entender porue os projetistas fizeram as
Pg: 2 de 69.
op%*es ue fizeram! e porue introduziram certos recursos espec(ficos na linguagem!
ent&o ser muito mais fcil compreender a linguagem integralmente.
O projeto de linguagens de programa%&o um processo evolucionrio. Uma nova
linguagem criada a partir de li%*es aprendidas com linguagens antigas! ou na tentativa
de introduzir novos recursos e facilidades a uma linguagem e$istente. 0or e$emplo! a
linguagem )da foi projetada originalmente para resolver um problema aflitivo enfrentado
pelo 0entgono. Os programadores! escrevendo cCdigo para diferentes sistemas de
defesa militar! tin#am usado centenas de linguagens de programa%&o diferentes! o ue
tornaria! de fato! imposs(vel manter ou aprimorar esses sistemas no futuro. )da tenta
resolver alguns desses problemas combinando os bons recursos de vrias linguagens em
uma 'nica linguagem de programa%&o.
Um outro bom e$emplo o processo evolucionrio ue ocorreu com as linguagens de
programa%&o a partir do desenvolvimento das linguagens estruturadas. +ssas linguagens
vieram em resposta a um grande problema n&o previsto pelos projetistas das linguagens
de programa%&o mais antigas6 o uso abusivo do comando goto em programas muito
grandes. +m um programa peueno o comando goto n&o causa maiores problemas. Das
em um programa muito grande! especialmente uando desenvolvido por algum viciado
no comando goto! os problemas tornam-se terr(veis. O cCdigo torna-se absolutamente
incompreens(vel por um outro programador ue tente l-lo pela primeira vez. )s
linguagens de programa%&o evolu(ram para resolver esse problema! eliminando o
comando goto inteiramente! e tornando simples subdividir um programa muito grande em
mCdulos ou fun%*es peuenas! compreens(veis e manejveis.
C++ uma linguagem orientada a objeto. 0rograma%&o orientada a objeto uma rea%&o
a problemas ue foram percebidos pela primeira vez em programas muito grandes
desenvolvidos na dcada de 3E. /odas as linguagens orientadas a objeto tentam atingir
trs objetivos! como uma forma de impedir ue ocorram os problemas inerentes a projetos
muito grandes6
/odas as linguagens de programa%&o orientadas a objeto implementam data abstraction
de uma forma clara usando um conceito denominado classes. ,amos e$aminar data
abstraction em maiores detal#es mais adiante! at porue esse um conceito central!
muito importante! em C++. +m poucas palavras! data abstraction um modo de
combinar dados e as funes usadas para manipul-los, de tal forma que os
detalhes da implementao fiquem ocultos para outros programadores. Data
abstraction possibilita o desenvolvimento de programas mais fceis de manter e de
aprimorar. /odas as linguagens orientadas a objeto tentam tornar facilmente reutilizveis e
e$tens(veis cada uma das partes ue comp*em os programas. )ui ue o termo ob$eto
come%a a fazer sentido. Os programas s&o uebrados! subdivididos! em objetos
reutilizveis. +sse objetos podem ser agrupados de diferentes maneiras para formar
novos programas. Objetos e$istentes podem ainda ser estendidos. 5ando aos
programadores um modo muito simples de reutilizar cCdigo! e virtualmente for%ando os
programadores a escrever cCdigos para serem reutilizados! torna-se muito mais fcil
desenvolver novos programas remontando pe%as j e$istentes.
Pg: 3 de 69.
Linguagens orientadas a obeto !isam tornar um c"digo e#istente facilmente
modific!el sem, na realidade, alterar fisicamente o c"digo. +sse um conceito 'nico
e muito poderoso! porue a primeira vista parece n&o ser poss(vel modificar alguma coisa
sem de fato alter-la. +ntretanto! plenamente poss(vel fazer isso usando dois novos
conceitos6 heran*a e polimor<ismo. $ obeto e#istente permanece o mesmo, e as
alteraes so como que assentadas sobre ele. ) #abilidade dos programadores para
manter e aprimorar cCdigo de um modo livre de erros drasticamente mel#orada usando
essa abordagem.
Como C++ uma linguagem orientada a objeto! ela contm os trs benef(cios da
orienta%&o a objeto recm apresentados. C++ acrescenta ainda a tudo isso duas outras
importantes mel#orias! para eliminar problemas e$istentes na linguagem C original! e para
tornar a programa%&o em C++ mais fcil ue em C.
C++ acrescenta um conceito denominado sobrecarga de operador. +sse recurso
permite ue voc especifiue em seus programas novos modos de uso para operadores
padr*es! tais como + e CC. 0or e$emplo! se voc uiser adicionar um novo tipo de dado!
como um tipo nmero complexo em um programa em C! tal implementa%&o n&o ser
simples. 0ara somar dois n'meros comple$os! voc ter ue criar uma fun%&o
denominada! por e$emplo! soma! e ent&o escrever c"DsomaEc4,c5FG! onde c4! c5 e c"
s&o valores do novo tipo n'mero comple$o. +m C++ voc pode! ao invs de criar uma
nova fun%&o! sobrecarregar os operadores + e D! de tal forma ue voc pode escrever
c"Dc4+c5. 5essa maneira! novos tipos de dados podem ser adicionados " linguagem de
uma maneira clara! simples! sem ajeitamentos. O conceito de sobrecarga aplica-se a
todas as fun%*es criadas em C++.
C++ ainda simplifica a implementa%&o de vrias partes da linguagem C! principalmente no
ue se refere a opera%*es de IFO e aloca%&o de memCria. +ssas novas implementa%*es
foram criadas contemplando-se a sobrecarga de operadores! de tal modo ue tornou-se
fcil adicionar novos tipos de dados e providenciar opera%*es de IFO e aloca%&o de
memCria para os novos tipos! sem truues ou artif(cios.
,amos e$aminar alguns problemas ue voc provavelmente enfrentou usando a
linguagem C! e ent&o ver como eles s&o resolvidos pelo C++
O primeiro problema pode ser visto em toda biblioteca de programas constru(da em C. O
problema demonstrado no cCdigo a seguir! o ual atribui um valor a um string e ent&o
concatena esse valor a um outro string6
char s[100];
strcpy(s, "hello ");
strcat(s, "world");
+ssa codifica%&o n&o muito bonita! mas o seu formato ilustra muito tipicamente o ue se
encontra em bibliotecas criadas em C. O tipo string constru(do a partir do tipo matriz-
de-caracteres! ue nativo em C. 5evido ao fato de ue o novo tipo! string! n&o parte
integrante da linguagem original! o programador for%ado a usar c#amadas de fun%*es
para fazer ualuer opera%&o com o novo tipo de dado. O desejvel ue! ao invs disso!
Pg: 4 de 69.
se possa criar novos tipos de dados e lidar com eles naturalmente! com os prCprios
recursos da linguagem. )lguma coisa como
string s;

s = "hello ";
s += "world";
.e algo assim poss(vel! a linguagem pode ser estendida ilimitadamente. C++ suporta
esse tipo de e$tens&o atravs da sobrecarga de operadores e de classes. Gepare ainda
ue usando um novo tipo string! a implementa%&o tornou-se completamente oculta. Ou
seja! voc n&o precisa saber como! ou se !o tipo string foi criado usando uma matriz de
caracteres! uma lista ligada! etc. ou ainda se string tem um taman#o m$imo. Del#or
ainda! fcil alterar-se! no futuro! a implementa%&o do tipo string! sem afetar
negativamente os cCdigos ue estiverem utilizando-o
Outro e$emplo usando uma biblioteca pode ser visto na implementa%&o de uma biblioteca
para tratamento de pil#as.
Os protCtipos das fun%*es para uma t(pica biblioteca de tratamento de pil#as -
normalmente encontrado no header <ile - mostrado a seguir6
void stack_init(stack s, int a!_si"e);
int stack_p#sh(stack s, int val#e);
int stack_pop(stack s, int $val#e);
void stack_clear(stack s);
void stack_destroy(stack s);
O programador usurio dessa biblioteca pode usar fun%*es para push! pop e clear a
pil#a! mas antes! e para ue ualuer uma dessas opera%*es seja vlida! de inicializar a
pil#a com a fun%&o stacHIinit. )o concluir com a utiliza%&o da pil#a! deve destru(-la com a
fun%&o stacHIdestroJ. + o ue acontece se voc se esuece da inicializa%&o ou da
destrui%&oA +m um caso real! o cCdigo n&o vai funcionar e pode ser bem dif(cil rastrear o
problema! a menos ue todas as rotinas dessa biblioteca detectem a falta da inicializa%&o
e indiuem isso especificamente. ) omiss&o da etapa de destrui%&o da pil#a pode causar
um problema denominado memory lea%! ue tambm dif(cil de rastrear. C++ resolve
esse problema usando construtores e destrutores! ue automaticamente manejam a
inicializa%&o e a destrui%&o de objetos! inclusive de pil#as.
Continuando ainda com o e$emplo da pil#a! note ue a pil#a! uma vez definida! pode
push e pop n'meros inteiros. O ue acontece se voc uer criar uma outra pil#a para
lidar com n'meros reais! ou uma outra ainda para caracteresA ,oc ter ue criar trs
bibliotecas separadas! ou! alternativamente! usar uma union e dei$ar a union manejar
todos os tipos de dados poss(veis. +m C++! um conceito denominado modelo permite
ue voc crie uma 'nica biblioteca para tratar a pil#a e redefina os tipos de dados a
serem armazenados na pil#a uando esta for declarada.
Um outro problema ue voc j deve ter tido programando em C envolve a altera%&o de
Pg: 5 de 69.
bibliotecas. 5igamos ue voc esteja usando a fun%&o print< definida na biblioteca stdio!
mas voc uer modific-la para manejar um novo tipo de dado ue voc criou em seu
programa. +$emplificando! voc deseja modificar print< para ue ela imprima n'meros
comple$os. ,oc n&o tem como fazer isso! a menos ue voc ten#a o cCdigo fonte da
implementa%&o de print<. Das ainda ue voc ten#a o cCdigo fonte de print<! essa pode
ser uma pssima estratgia porue voc pode gerar um cCdigo n&o portvel. H&o #
realmente um modo de e$tender facilmente uma biblioteca C uma vez ue ela ten#a sido
compilada. 0ara resolver o problema de impress&o de n'meros comple$os em C! como
no nosso e$emplo! voc teria ue criar uma nova fun%&o com a mesma finalidade ue
print<. .e voc tiver vrios novos tipos de dados! voc ter ue criar vrias e diferentes
novas fun%*es de sa(da! " semel#an%a de print<. C++ lida com todos esses problemas
com uma nova tcnica para sa(da padr&o. Uma combina%&o de sobrecarga de operador e
classes permite integrar novos tipos de dados ao esuema padr&o de IFO do C++.
)inda pensando sobre a fun%&o print<! reflita sobre seu projeto e pergunte-se a si mesmo6
+sse um bom modo de se projetar um cCdigoA 5entro do cCdigo de print< # um
comando switch! ou uma cadeia de i<AelseAi< ue avalia um string de formata%&o da
sa(da. Um !d usado para n'meros decimais! um !c usado para caracteres! um !s
usado para strings! e assim por diante. -! no m(nimo! trs problemas com essa
implementa%&o6
O programador da implementa%&o de print< tem ue manter o comando switch! ou
cadeia de i<AelseAi<! e modific-lo para cada novo tipo de formata%&o ue se uiser
implementar. Dodifica%*es sempre significam a possibilidade de se introduzir novos bugs.
H&o # ualuer garantia de ue o programador usurio de print< vai combinar
corretamente o tipo do dado com string de formata%&o! o ue significa ue a fun%&o
contm um risco de fal#a.
+ssa implementa%&o n&o e$tens(vel! a menos ue voc possua o cCdigo fonte! voc
n&o pode ampliar as capacidades de print<.
C++ resolve esses problemas completamente porue for%a o programador a estruturar o
cCdigo de uma nova maneira. O comando switch ocultado e manejado
automaticamente pelo compilador atravs da sobrecarga de fun%&o. /orna-se assim
imposs(vel combinar erradamente os parImetros ao invocar uma fun%&o! primeiro porue
eles n&o s&o implementados como parImetros em C++! e segundo porue o tipo da
varivel controla automaticamente o mecanismo de switch ue implementado pelo
compilador.
C++ resolve ainda vrios outros problemas. 0or e$emplo! resolve o problema de c"digo
comum replicado em !rios lugares! permitindo ue voc controle cCdigo comum em
uma terceira dimens&o. Gesolve o problema eu quero alterar o tipo de dado passado
para uma funo sem alterar a funo! permitindo ue voc sobrecarregue o mesmo
nome de fun%&o com m'ltiplas listas de parImetros. Gesolve o problema eu quero fa&er
uma pequena alterao no modo como isso funciona, mas eu no tenho o c"digo
fonte! e ao mesmo tempo resolve o problema eu quero reformular essa funo
Pg: 6 de 69.
inteiramente, sem alterar o restante da biblioteca usando o conceito de #eran%a.
C++ torna a cria%&o de bibliotecas mais simples e mel#ora drasticamente a tarefa de
manuten%&o do cCdigo. + muito mais.
,oc precisar mudar um pouco o seu modo de pensar em programa%&o para obter as
vantagens de todos esses recursos poderosos! e isso significa ue voc vai ter ue
dedicar-se um pouco mais ao projeto de seu cCdigo. .em isso! voc perder vrios dos
benef(cios do C++. Como em tudo na vida! a migra%&o para C++ significa custos e
benef(cios! mas nesse caso o conjunto dos benef(cios supera em muito os custos.
E;tensKes ao C
5.0 Introdu%&o
5.4 Comentrios
5.5 Convers&o de tipos de dados
5." InputFOutput
5.6 5eclara%*es de variveis
5.7 Constantes
5.8 .obrecarregando fun%*es
5.9 )rgumentos default
5.# )loca%&o de memCria
5.L 5eclara%*es de referncia
5.0 M Introdu*+o
/udo o ue voc j escreveu em C funciona em C++. Ho entanto! em muitos casos C++
oferece um modo mel#or de se realizar o mesmo trabal#o. +m outros casos C++ oferece
mais de uma maneira de se fazer a mesma coisa! e isso l#e d maior fle$ibilidade no
desenvolvimento de programas. Hessa se%&o vamos e$aminas as e$tens*es do C++ em
rela%&o ao C. Duitas dessas e$tens*es n&o foram adicionadas gratuitamente! mas sim
para viabilizar programa%&o orientada a objeto! conforme se ver mais adiante em outros
tutoriais dessa srie.
+sse tutorial em especial apresenta muitos detal#es do C++. Hada de pInico. .e preferir
apenas percorra o te$to e volte mais tarde estudando cada se%&o! na medida de sua
necessidade. Os conceitos apresentados a seguir foram todos reunidos aui para
simplifica%&o de referncia! j ue ser&o usados em vrios outros pontos dessa srie de
tutoriais.
5.4 M Coment2rios
C++ suporta o antigo modo multilin#a de comentrio! bem como a nova forma lin#a 'nica
representado pelo s(mbolo FF. 0or e$emplo6
%% get_it &#nction reads in inp#t val#es
void get_it()
'
Pg: 7 de 69.
%% do soething(
)
O C++ ignora tudo o ue estiver escrito apCs o FF e at o final da lin#a. ,oc pode usar
ambas as formas de comentrio em um programa C++.
5.5 A Con'ers+o de tipos de dados
+m C voc pode determinar a convers&o de tipos de dados! colocando o nome do tipo
entre parntesis imediatamente antes do nome da varivel! como no e$emplo seguinte6
int i;
&loat &;

& = (&loat) i;
C++ suporta um segundo modo de convers&o de tipos! ue faz com ue a especifica%&o
de convers&o se pare%a mais com a c#amada de uma fun%&o6
int i;
&loat &;

& = &loat(i);
,amos ver mais adiante! uando come%armos a tratar de classes! ue # uma raz&o para
esse novo formato.
5." M Input / @utput
5.".4 A I/@ em Nerminal
Uma das mais Cbvias diferen%as entre C e C++ a substitui%&o da biblioteca stdio do C
pela iostream do C++. ) biblioteca iostream beneficia-se de um grande n'mero de
e$tens*es do C++ voltadas a orienta%&o a objeto! conforme veremos mais adiante. Dais
ainda! torna mais fcil a adi%&o de novos tipos de dados definidos pelo programador. )
biblioteca iostream contm todas as capacidades encontradas na stdio! mas as viabiliza
de uma nova forma. 0ortanto! importante con#ecer como usar as fun%*es bsicas da
iostream se voc estiver convertendo seu cCdigo de C para C++. O uso de iostream
para as fun%*es bsicas de input / output de compreens&o uase imediata. ,eja os
seguintes e$emplos6
co#t ** "hello+n";
ou o euivalente6
co#t ** "hello" ** endl;
)mbos os e$emplos produzem a mesma sa(da! e fazem com ue a palavra hello seguida
de um newline seja escrita na unidade padr&o de sa(da. ) palavra cout indica stdout
como destina%&o para a opera%&o de sa(da! e o operador OO 8ue significa inser%&o?
usado para transferir os itens de dados. - duas outras sa(das-padr&o pr-definidas6 cerr
para notifica%*es imediatas de erro! e clog para acumula%&o de notifica%*es de erro.
Pg: 8 de 69.
0ode-se escrever em ualuer sa(da padr&o usando-se as tcnicas mostradas no
e$emplo anterior. D'ltiplos itens de dados podem ser enfileirados em uma 'nica lin#a de
comando! ou empil#ados em vrias lin#as. 0or e$emplo6
int i = ,;
&loat & = -(1.
char c = /0/;
char $s = "hello";

co#t ** s ** c ** & ** i ** endl;
produz a sa(da6
helloA".465
da mesma forma ue6
co#t ** s ** c;
co#t ** &;
co#t i ** endl;
O mecanismo cout compreende valores de endere%os de memCria automaticamente! e
os formata para apresenta%&o em #e$adecimal. 0or e$emplo! se i um inteiro! ent&o o
comando6
co#t ** 1i ** endl;
- casos! no entanto! em ue essa regra de convers&o para #e$adecimal n&o se aplica.
Imprimir s! onde s um pointer para um caracter! produz a impress&o do string apontado
por s em lugar do endere%o contido em s. 0ara remediar essa situa%&o! converta s para
um pointer 'oid! como mostrado a seguir! se o ue voc uer a impress&o do endere%o
contido de s6
co#t ** (void $) s;
)gora o endere%o contido em s ser apresentado em formato #e$adecimal. .e voc
uiser o endere%o apresentado em formato decimal! converta-o para um inteiro longo6
co#t ** long(1 i);
+ssa lin#a imprime o endere%o de i em formato decimal.
5a mesma forma! uma convers&o para int usada para imprimir o valor inteiro de um
caracter6
co#t ** int(/0/); %% prod#ces 23 as o#tp#t
,oc pode estran#ar ue o operador OO - con#ecido em C como shi<t le<t operator -
ten#a sido roubado para manejar opera%*es de sa(da em C++. .e voc uiser us-lo para
opera%&o de shi<t le<t dentro de uma lin#a de sa(da! use-o entre parntesis6
co#t ** (, ** .); %% prod#ces -, as o#tp#t
Pg: 9 de 69.
,oc pode usar vrias tcnicas para formatar a sa(da. Informa%*es podem ser espa%adas
acrescentando-se espa%os! tabs ou strings literais! como mostrado a seguir6
int i = ,;
&loat & = -(1.
char c = /0/;
char $s = "hello";

co#t ** s ** " " ** c ** "+t" ** &
** "+t" ** i ** endl;
- ainda vrios outros manipuladores ue podem ser inseridos em um flu$o de sa(da 8em
alguns sistemas voc precisar incluir iomanip.h para poder us-las?6
dec Usa base decimal
oct Usa base octal
he; Usa base #e$adecimal
endl 1inaliza a lin#a
ends 1inaliza o string 8JKEJ?
<lush 5escarrega o buffer de sa(da
setwEwF +stabelece a largura da sa(da para o valor de L
8E o default?
set<illEcF +stabelece o caracter de preenc#imento para conte'do de c 8blanM o
default?
setprecisionEpF +stabelece a precis&o flutuante para o valor de p
O cCdigo
co#t ** "[" ** setw (2) ** set&ill(/$/) ** 14,;
co#t ** "]" ** endl;
co#t ** he! ** "[" ** setw (2);
co#t ** set&ill(/$/) ** 14, ** "]" ** endl;
co#t ** setprecision(.) ** -(1.134 ** endl;
produz
NOOO=PQR
NOOOOcER
>.=<Q
) sa(da de n'meros em ponto flutuante pode truncar ou n&o zeros a direita! independente
de como voc estabele%a a precis&o. +ssa uma caracter(stica determinada pelo
compilador ue voc estiver usando.
,oc deve ter notado nos e$emplos recm apresentados ue n&o se deve usar certos
nomes para variveis ou fun%*es para n&o se perder a possibilidade de usar os
manipuladores intr(nsecos " biblioteca iostream.
Pg: 10 de 69.
)s opera%*es de entrada s&o manejadas de uma maneira semel#ante "s opera%*es de
sa(da! usando-se cin para flu$o de entrada e CC como operador de e$tra%&o. 0or
e$emplo! o comando
int i,5,k;
cin 66 i 66 5 66 k;
O flu$o de entrada cin automaticamente divide o string de entrada em palavras e termina
uando recebe E@P.
5.".5 A I/@ em ar)ui'os
Input e output para aruivos te$to s&o manejados pela inclus&o do aruivo <stream.h! e
pela declara%&o de variveis do tipo i<stream e o<stream respectivamente. 0or e$emplo!
o seguinte programa l um aruivo denominado ;;; e escreve em um aruivo
denominado JJJ6
7incl#de *iostrea(h6
7incl#de *&strea(h6

void ain()
'
char c;
i&strea in&ile("!!!");
o&strea o#t&ile("yyy");

i& (o#t&ile 11 in&ile) %% 8hey will 9e 0 on err(
while (in&ile 66 c)
o#t&ile ** c;
)
)s variveis in<ile e out<ile recebem o nome do aruivo na inicializa%&o e s&o usadas
e$atamente como cin e cout. O cCdigo desse e$emplo n&o funciona como seria de
esperar porue brancos! tabs e caracteres Q0 ao final de cada lin#a s&o ignorados! do
mesmo modo ue espa%o em branco uando se usa OO. Hesse caso! mel#or usar a
fun%&o get! como mostrado a seguir6
while (in&ile(get(c))
o#t&ile ** c;
ou
while (in&ile(get(c))
o#t&ile(p#t(c);
@ ainda poss(vel ler lin#as inteiras usando-se a fun%&o getline! da mesma maneira ue se
usa a fun%&o get. 0ara abrir um aruivo para acrescentar dados! use o seguinte6
o&strea("!!!", iosapp);
+ssa lin#a! bem como a nota%&o da fun%&o .get! far mais sentido na medida em ue
voc con#e%a mais sobre o C++. O fato de o<stream algumas vezes receber um! outras
Pg: 11 de 69.
vezes dois parImetros uma caracter(stica intr(nseca ao C++.
Hote ue n&o # necessidade de uma fun%&o close para os aruivos de entrada ou de
sa(da. O aruivo fec#ado automaticamente uando se encera o escopo da varivel ue
denomina o aruivo. .e voc precisar fec#ar e$plicitamente um aruivo! use
o#t&ile(close();
5."." A I/@ em string
+ntradas podem ser lidas a partir de string na memCria! e sa(das pode ser enviadas para
strings na memCria! duplicando-se assim as a%*es de sscan< e sprint<. 0ara tanto voc
deve incluir o aruivo strstream.h e declarar a entrada e a sa(da em string. Uma sa(da
em string e mostrada a seguir6
char s[100];
ostrstrea o#tstring(s,100);

o#tstring ** -(1. ** " is pi" ** ends;
co#t ** s;
O string s preenc#ido com o te$to
".46 is pi.
.e o taman#o de s for atingido! outstring vai automaticamente interromper a coloca%&o
de valores em s.
.e um string s j e$iste e voc deseja ler dados a partir dele! voc pode usar um flu$o de
entrada string como mostrado a seguir6
char $s = "-(1. 1, cat";
istrstrea instring(s, strlen(s));
&loat &;
int i;
char t[100];

instring 66 & 66 i 66 t;
) biblioteca iostream tem muitas e muitas outras capacidades n&o discutidas aui. 0ara
maiores informa%*es! veja a documenta%&o fornecida junto com o seu compilador. +la
geralmente contm uma referncia completa para a biblioteca de I/@.
5.6 A Declara*Kes de 'ari2'eis
,ariveis s&o declaradas em C++ assim como o s&o em C. )s variveis podem ser
declaradas em ualuer ponto do cCdigo em C++! estabelecendo um n(vel de fle$ibilidade
uase como o ue e$iste em 1OG/G)H. ) varivel torna-se e$istente uando
declarada! e dei$a de e$istir uando o R do bloco corrente encontrado. 0or e$emplo! na
seguinte codifica%&o6
'
Pg: 12 de 69.
int i;
((( code (((
int 5;
((( code (((
int k=&#nc(i,5);
((( code (((
)
todas as trs variveis passam a e$istir no ponto em ue s&o declaradas! e desaparecem
ao R.
5.7 M Constantes
+m C voc cria uma constante usando uma macro do pr-processador! como no seguinte
e$emplo6
7de&ine :0; 100
Buando o programa compilado! o pr-processador encontra cada ocorrncia da palavra
D)S e a substitui pelo string =EE.
+m C++ usa-se a palavra const! ue aplicvel normalmente "s declara%*es de
variveis6
const int :0;=100;
) codifica%&o int SATD400G formatada e$atamente da mesma maneira ue uma
declara%&o normal. O termo const ue precede a declara%&o simplesmente define ue a
varivel SAT n&o pode ser modificada. O uso de letras mai'sculas para nomes de
variveis constantes uma tradi%&o em C! ue voc pode preservar ou abandonar.
O modificador const pode tambm ser usado em listas de parImetros para especificar o
uso correto do parImetro. )s trs fun%*es a seguir e$emplificam diferentes usos de
const.
void &#nc1(const int i)
'
i=3; %% cannot odi&y a constant
)

void &#nc,(char $ const s)
'
s="hello"; %% cannot odi&y the pointer
)

void &#nc-(const char $ s)
'
s="hello"; %% this is <=
$s=/0/; %% cannot odi&y what is pointed to
)
) nota%&o mostrada em <unc5 deve! sempre ue poss(vel! ser usada uando um
Pg: 13 de 69.
parImetro char U passado para a fun%&o.
5.8 A &obrecarregando <un*Kes
Um dos mais poderosos novos recursos do C++ denominado sobrecarga de <un*+o.
Uma fun%&o sobrecarregada possui vrias e diferentes listas de parImetros. ) linguagem
distingue ual das op%*es de c#amada da fun%&o deve ser usada! com base no padr&o
das listas de parImetros. )ui est uma demonstra%&o e$tremamente simples desse
processo6
7incl#de *iostrea(h6

void &#nc(int i)
'
co#t ** "&#nction 1 called" ** endl;
co#t ** "paraeter = " ** i ** endl;
)

void &#nc(char c)
'
co#t ** "&#nction , called" ** endl;
co#t ** "paraeter = " ** c ** endl;
)

void &#nc(char $s)
'
co#t ** "&#nction - called" ** endl;
co#t ** "paraeter = " ** s ** endl;
)

void &#nc(char $s, int i)
'
co#t ** "&#nction . called" ** endl;
co#t ** "paraeter = " ** s;
co#t ** ", paraeter = " ** i ** endl;
)

ain()
'
&#nc(10);
&#nc(/>/);
&#nc("hello");
&#nc("string", .);
ret#rn 0;
)
Buando esse cCdigo e$ecutado! cada vers&o da fun%&o <unc escol#ida! e c#amada!
de acordo com as correspondncias entre as listas de parImetros. .oc( 'ai conseguir
usar essa capacidade, )ue : uma grande caracter1stica do C++, uma 'e= )ue 'oc(
encare sobrecarga de <un*+o como uma solu*+o para muitos dos problemas de
programa*+o. 0or e$emplo! se voc cria uma fun%&o para inicializar um mCdulo! voc
pode ter uma c#amada diferente! para a mesma fun%&o! dependendo da caracter(stica do
parImetro ue passadoT um string! um inteiro! um ponto flutuante! e assim por diante.
Pg: 14 de 69.
5.9 A Argumentos de<ault
C++ tambm permite ue voc determine valores default para os parImetros. .e o
parImetro n&o for passado! o valor default usado. +ssa capacidade demonstrada no
seguinte cCdigo6
7incl#de *iostrea(h6

void saple(char $s, int i=3)
'
co#t ** "paraeter 1 = " ** s ** endl;
co#t ** "paraeter , = " ** i ** endl;
)

ain()
'
saple("test1");
saple("test1",10);
ret#rn 0;
)
) primeira c#amada da fun%&o vai apresentar o valor default 7 para o parImetro i!
enuanto a segunda c#amada vai apresentar o valor 40.
Buando criando parImetros default! voc precisa evitar ambiguidade entre as listas de
parImetros default e as demais listas de parImetros. +$aminando a fun%&o de nosso
'ltimo e$emplo! n&o poss(vel criar uma vers&o sobrecarregada ue aceite um parImetro
char U isolado! porue o compilador n&o conseguiria escol#er ue vers&o c#amar no caso
de se passar um string.
5.# A Aloca*+o de mem-ria
C++ substitui as fun%*es C de aloca%&o e de desaloca%&o de memCria ! malloc e <ree!
pelas novas fun%*es new e delete! respectivamente e torna esse processo muito mais
fcil para o programador. neL e delete permitem ue tipos de dados definidos pelo
programador sejam alocados e desalocados t&o facilmente uanto os tipos j e$istentes
em C++.
O cCdigo seguinte e$emplifica o modo mais simples de uso de new e delete. Um pointer
para um inteiro aponta para um bloco de memCria criado por new6
int $p;
p = new int;
$p = 1,;
co#t ** $p;
delete p;
@ ainda poss(vel alocar blocos compostos de matrizes de taman#os variados! usando
uma tcnica similar. Gepare o uso de V W para e$cluir a matriz6
int $p;
Pg: 15 de 69.
p = new int[100];
p[10] = 1,;
co#t ** p[10];
delete [] p;
O valor =EE poderia ser uma varivel! se desejvel.
Buando aplicada a tipos de dados definidos pelo programador! new funciona do mesmo
modo. 0or e$emplo6
typede& node
'
int data;
node $ne!t;
) node;

ain()
'
node $p;
p=new node;
p?6date = 10;
delete p;
)
Conforme veremos mais adiante nessa srie de tutoriais! o operador delete bastante
sofisticado uando opera com classes definidas pelo programador.
5.L A Declara*Kes de re<er(ncia
+m C! pointers s&o freuentemente usados para passar parImetros para fun%*es. 0or
e$emplo! a seguinte fun%&o swap inverte dois valores ue l#e s&o passados6
void swap(int $i, int $5)
'
int t = $i;
$i = $5;
$5 = t;
)

ain()
'
int a=10, 9=3;

swap(1 a, 1 9);
co#t ** a ** 9 ** endl;
)
C++ prov um novo operador de re<er(ncia ue simplifica muito essa sinta$e. O seguinte
cCdigo funciona em C++
void swap(int1 i, int1 5)
'
int t = i;
Pg: 16 de 69.
i = 5;
5 = t;
)

ain()
'
int a=10, 9=3;

swap(a, 9);
co#t ** a ** 9 ** endl;
)
Os parImetros i e $ declarados como tipo intX atuam como referncias para os inteiros
passados 8leia intX como uma referncia para um inteiro?. Buando uma varivel
atribu(da " referncia de uma outra varivel! a referncia toma o endere%o da varivel e
opera a atribui%&o para a localiza%&o real para a varivel . 0or e$emplo6
int a;
int 1 9=a;

a=0;
9=3;
co#t ** a ** endl;
O cCdigo acima produz 7 como sa(da porue b referencia a. @ o mesmo ue usar pointer
e operadores de endere%os em C! mas a sinta$e aui muito mais simples. Hote ue b
deve ser inicializado uando de sua cria%&o! como mostrado no e$emplo.
.ocabul2rio C++
".0 Introdu%&o
".4 ,ocabulrio C++
".5 ) evolu%&o das classes
"." C++ e abstra%&o de dados
".0 M Introdu*+o
O 'ltimo tutorial enfocou elementos da linguagem C++ ue e$tendem as capacidades
originais! ou corrigem problemas inerentes " linguagem C. +ssas e$tens*es s&o bastante
simples de se entender.
O outro conjunto de recursos do C++ s&o dirigidas " programa%&o orientada a objeto! e
talvez n&o sejam de entendimento t&o imediato. +nuanto as capacidades de cout s&o
apenas uma outra forma de manejar opera%*es de sa(da de dados - as uais voc j
con#ecia previamente - algumas e$tens*es orientadas a objeto talvez n&o l#e sejam t&o
familiares. O objetivo desse cap(tulo l#e dar uma primeira e$posi%&o de algumas dessas
e$tens*es. )ssim! vamos e$aminar a sinta$e C++ ue suporta os conceitos de orienta%&o
a objeto e posteriormente rever os conceitos.
".4 A .ocabul2rio C++
Pg: 17 de 69.
Ol#e o mundo a sua volta. ,oc pode entender uma grande parte da estrutura! do
vocabulrio e da organiza%&o do C++ apenas ol#ando a estrutura e a organiza%&o do
mundo real! e refletindo sobre o vocabulrio ue usamos para falar sobre o mundo real.
Duitos dos elementos do C++ - em da orienta%&o a objeto em geral - tentam emular o
modo como interagimos com o mundo real.
0or e$emplo! sempre ue voc ol#a em torno voc v uma grande uantidade de
ob$etos. HCs organizamos esses objetos em nossas mentes arranjando-os em
categorias! ou classes. .e voc tem um livro em suas m&os! um li'ro : uma classe
gen:rica de ob$etos. ,oc poderia dizer 7esse ob$eto )ue eu tenho nas m+os :
classi<icado como um li'ro.7 Uma #ieraruia de classes de objetos envolve a classe
livro e a estende em duas dire%*es. 9ivros s&o membros da classe mais geral
publica%*es. - ainda tipos espec(ficos de livros! tais como livros de computa%&o! livros
de fic%&o! biografias! e assim por diante. ) organiza%&o #ierruica se estende em ambos
os sentidos6 do mais geral para o mais espec(fico. +m nosso e$emplo! voc tem nas
m&os um determinado livro! um livro espec(fico. Ho idioma OO0! voc tem nas m&os uma
instYncia da classe li'ro. 9ivros tem certos atributos ue s&o comuns e portanto s&o
compartil#ados por todos os livros6 uma capa! vrios cap(tulos! n&o tem an'ncios! etc.
9ivros tem tambm atributos comuns a publica%*es em geral6 t(tulo! data de publica%&o!
editora! etc. /em ainda atributos comuns a objetos f(sicos6 localiza%&o! taman#o! forma e
peso. +ssa idia de atributos comuns muito importante em C++. C++ modela o conceito
de atributos comuns usando heran*a.
- certas coisas ue voc faz com e para certos objetos! e essas a%*es s&o diferentes de
objeto para objeto. 0or e$emplo! voc pode ler um livro! fol#ear suas pginas. ,oc pode
ol#ar um t(tulo! procurar um cap(tulo espec(fico! pesuisar o (ndice! contar o n'mero de
pginas! etc. +ssas a%*es s&o aplicveis unicamente a publica%*es. ,oc n&o poderia
fol#ear as pginas de um martelo! por e$emplo. +ntretanto! # a%*es ue s&o genricas e
aplicveis a todos os objetos f(sicos! como peg-los. C++ tambm leva em conta esse
fato e modela esses casos usando heran*a.
) natureza #ierruica das categorias de objetos! bem como nossa organiza%&o
#ierruica de atributos de objetos e de a%*es! est&o contidas na sinta$e e no vocabulrio
do C++. 0or e$emplo! uando projetando um programa voc vai subdividi-lo em objetos!
cada um dos uais tem uma classe. ,oc vai #erdar atributos de uma classe base
uando voc criar uma classe deri'ada. Ou seja! voc vai criar classes mais gerais de
objetos e ent&o fazer classes mais espec(ficas! a partir das classes gerais! deri'ando o
particular a partir do geral. ,oc vai encapsular o dados em um objeto com fun%*es
membro fun%*es membro fun%*es membro fun%*es membro fun%*es membro fun%*es
membro! e para ampliar classes voc vai sobrecarregar e sobrescrever fun%*es da classe
base. ConfusoA ,amos e$aminar um e$emplo simples para ver o ue esses termos
significam na realidade.
O e$emplo clssico de programa%&o orientada a objeto um programa grfico ue l#e
permite desen#ar objetos - lin#as! retIngulos! c(rculos! etc. - na tela do terminal. O ue
todos esses objetos tem em comumA Bue atributos todos esses objetos compartil#amA
/odos tem uma localiza%&o na tela. 0odem ter uma cor. +sses atributos - localiza%&o e cor
- s&o comuns a todas as formas e$ibidas na tela. 0ortanto! como projetista do programa
voc poderia criar uma classe base - ou em outras palavras! uma classe genrica de
objetos - para conter os atributos comuns a todos os objetos apresentados na tela. +ssa
classe base poderia ser denominada 1orma! para mel#or identific-la como classe
Pg: 18 de 69.
genrica. ,oc poderia ent&o derivar diferentes objetos - c(rculos! uadrados! lin#as - a
partir dessa classe base! adicionando os novos atributos ue s&o prCprios de cada forma
em particular. Um c(rculo espec(fico desen#ado na tela uma instIncia da classe C(rculo!
ue #erdou uma parte de seus atributos de uma classe mais genrica denominada
1orma. @ poss(vel criar tal conjunto de #ieraruia em C! mas nem de longe com tanta
facilidade uanto em C++. C++ contm sinta$e para tratar #eran%a. 0or e$emplo! em C
voc poderia criar uma estrutura bsica para conter os atributos localiza%&o e cor dos
objetos. )s estruturas espec(ficas de cada objeto poderiam incluir essa estrutura bsica e
ampli-la. C++ torna esse processo mais simples. +m C++! as fun%*es s&o agrupadas!
reunidas dentro de uma estrutura! e essa estrutura denominada classe. )ssim! a classe
base pode ter fun%*es! denominadas em C++ como fun%*es membro! ue permitam ue
os objetos sejam movidos ou recoloridos. )s classes derivadas podem usar essas
fun%*es membro da classe base tal como s&o! criar novas fun%*es membro! ou ainda
sobrescrever fun%*es membro da classe base.
O mais importante recurso ue diferencia C++ do C a ideia de classe! tanto em n(vel
sinttico uanto em n(vel conceptual. Classes permitem ue voc use todas as facilidades
de programa%&o orientada a objeto - encapsulamento! #eran%a e polimorfismo - em seus
programas em C++. Classes s&o ainda a estrutura bsica sobre a ual outros recursos
s&o implementados! como sobrecarga de operador para novos tipos de dados definidos
pelo programador. /udo isso pode l#e parecer confuso ou desarticulado nesse momento!
mas na medida em voc de torne familiarizado com os conceitos e com esse vocabulrio
vai perceber todo o poder dessas tcnicas
".5 A A e'olu*+o das classes
+ntendidos os conceitos poderosos agregados ao conceito de classe! a compreens&o da
sinta$e torna-se uase automtica. Uma classe simplesmente uma mel#oria das
estruturas em C. ;asicamente! uma classe possibilita )ue 'oc( crie uma estrutura
)ue contenha tamb:m todas as <un*Kes para lidar com os dados da estrutura. Esse
processo : denominado encapsulamento. @ um conceito muito simples! mas o ponto
central da orienta%&o a objeto6 dados + <un*Kes D ob$etos. Classes podem tambm ser
constru(das sobre outras classes! usando #eran%a. Com #eran%a! uma nova classe
amplia as capacidades da classe base. 1inalmente! novas classes podem modificar o
comportamento de suas classes base! uma capacidade denominada polimor<ismo.
+ssa uma nova maneira de pensar sobre o cCdigo6 uma abordagem tridimensional.
,oc pode considerar um cCdigo linear ! um ue n&o conten#a e nem invoue ualuer
fun%&o! como um cCdigo unidimensional. Um cCdigo ue come%a no in(cio e termina no
fim 8sic?. Hada mais. )gora voc acrescenta fun%*es a esse cCdigo linear! para remover
redundIncia de codifica%&o! e d nomes a essas por%*es de cCdigo! identificando assim
as fun%*es. Isso cCdigo bidimensional. )gora vamos acrescentar uma terceira dimens&o
a tudo isso agrupando as fun%*es e os dados em classes para ue o cCdigo fiue ainda
mais organizado. ) #ieraruia de classes criada pela #eran%a de classes estabelece a
terceira dimens&o. 5a mesma forma ue pilotar um avi&o mais dif(cil ue dirigir um
carro! porue voar acrescenta uma terceira dimens&o ao problema de guiar! programa%&o
orientada a objeto pode reuerer um certo tempo para ser completamente compreendida.
Uma das mel#ores maneiras para se entender classes e sua importIncia para voc como
programador aprender como e porue o conceito de classe evoluiu. )s ra(zes do
conceito de classe nos levam a um tCpico denominado abstra*+o de dados.
Pg: 19 de 69.
Imagine ue voc est ol#ando uma t(pica sala de estudantes de computa%&o c#eia de
alunos escrevendo programas. Imagine ue alguns desses estudantes s&o alunos do
primeiro semestre do curso de 0ascal. +les j sabem como criar comandos i<! loops e
matri=es e portanto est&o uase prontos a escrever cCdigo! mas n&o sabem ainda como
organizar o pensamento. .e voc pedir a um deles ue crie um programa! ele vai criar um
cCdigo ue funciona de ualuer maneira. H&o ser uma boa solu%&o! mas
provavelmente vai funcionar. Imagine agora ue voc pe%a a esses estudantes ue criem
um programa para e$ecutar o jogo cannon. Um jogo em ue os jogadores vm uma bola
e um alvo e obstculos no terreno. ) localiza%&o do alvo! o terreno e obstculos mudam
de jogo para jogo. O objetivo estabelecer um Ingulo de trajetCria e uma for%a a ser
aplicada a bola para ue esta atinja o alvo sem tocar em ualuer dos obstculos do
terreno.
)ssuma ue os dados do terreno e$istem em um aruivo te$to contendo pares de
coordenadas. )s coordenadas s&o pontos finais dos segmentos de lin#as ue definem o
terreno. Os estudantes imaginam ue precisam ler esse aruivo para poder desen#ar o
terreno! e ainda manter o aruivo em memCria para poder verificar as interse%*es da
trajetCria da bola com as coordenadas do terreno! e assim determinar o ponto do terreno
onde a bola para. +nt&o o ue eles fazemA 5eclaram uma matriz global para conter as
coordenadas! lem o aruivo e armazenam os dados na matriz! e usam a matriz onde for
necessrio! em ualuer ponto do programa.
O problema com essa abordagem ue a matriz est como ue embutida em todo o
cCdigo. .e uma altera%&o se fizer necessria! por e$emplo em lugar da matriz usar-se
uma lista ligada! o programa ter ue ser rescrito porue contm referncias e$pl(citas
para a matriz. 5e um ponto de vista de produ%&o de programas profissionais essa uma
pssima abordagem! porue as estruturas de dados freUentemente s&o alteradas em
sistemas de informa%&o reais.
Uma maneira mel#or de projetar o programa usar um tipo de dado abstrato. Hessa
abordagem! o programador primeiramente tem ue decidir como os dados ser&o usados.
+m nosso e$emplo do terreno! o programador poderia pensar 7Bem, eu preciso poder
carregar coordenadas do terreno, independentemente de onde !enham, para
desenhar o terreno na tela e para !erificar as intersees da traet"ria da bola com
os obstculos do terreno7. Gepare ue esta 'ltima abordagem abstraiAse da <orma
como os dados estar+o arma=enados! n&o fazendo ualuer men%&o a matriz ou lista
Pg: 20 de 69.
ligada. +nt&o o programador cria uma fun%&o para implementar as capacidades de ue
precisa. )s fun%*es poderiam ser denominadas
carrega_terreno
desenha_terreno
veri&ica_intersecoes(
+ssas fun%*es s&o usadas ao longo de todo o programa. As <un*Kes atuam como uma
barreira. Elas ocultam a estrutura dos dados, separandoAa do programa. .e mais
tarde a estrutura dos dados precisar ser alterada! por e$emplo de matriz para uma lista
ligada! a maior parte do programa n&o ser afetada. )penas as fun%*es precisar&o ser
modificadas. Dessa <orma o programador criou um tipo de dado abstrato.
)lgumas linguagens formalizam esse conceito. +m 0ascal voc pode usar um unit! em C
voc pode usar uma biblioteca para criar um aruivo de compila%&o em separado ue
contm a estrutura de dados e as fun%*es ue os processam. ,oc pode determinar ue
a estrutura de dados seja oculta! de tal maneira ue a matriz seja acessada
e$clusivamente pelas fun%*es internas " unidade.
Dais ainda! a unidade pode ser compilada para ocultar o prCprio cCdigo. )ssim! outros
programadores podem c#amar as fun%*es atravs de uma interface p'blica! mas n&o
podem modificar o cCdigo original.
Units em pascal e bibliotecas em C representam um passo nessa cadeia evolucionria.
Come%am a enfrentar o problema de abstra%&o de dados mas n&o v&o longe o bastante.
1unciona! mas com alguns problemas6
O mais importante deles ue n&o fcil modificar ou estender as capacidades de uma
unit apCs a compila%&o.
+sses tipos abstratos n&o se encai$am muito bem na linguagem original. .intaticamente
s&o uma confus&o! e n&o aceitam os operadores normais da linguagem. 0or e$emplo! se
voc cria um novo tipo de dado para o ual a opera%&o de adi%&o seria natural! n&o #
meios de voc usar o sinal + para representar a opera%&o! ao invs disso voc tem ue
criar uma fun%&o de soma.
.e voc ocultar uma matriz em uma unit voc poder ter apenas uma matriz. ,oc n&o
pode criar m'ltiplas instIncias de tipos de dados.
Classes em C++ eliminam essas deficincias
"." A C++ e abstra*+o de dados
+m resposta a esses problemas! linguagens orientadas a objeto como C++ oferece
modos fceis e e$tens(veis de se implementar abstra%&o de dados. /udo o ue voc tem
ue fazer mudar o seu enfoue! e passar a pensar em solu%&o de problemas com uma
abordagem abstrata. +ssa mudan%a de atitude mental ser mais fcil uando voc tiver
e$aminado alguns e$emplos.
0rimeiramente voc vai tentar pensar em termos de tipos de dados. Buando voc criar
Pg: 21 de 69.
um novo tipo de dado! voc precisa pensar em todas as coisas ue pretende fazer ele! e
ent&o agrupar todas as fun%*es criadas para lidar especificamente com o tipo de dado.
0or e$emplo! digamos ue voc est criando um programa ue reuer um tipo de dado
retYngulo! contendo dois pares de coordenadas. ,oc deveria pensar 7o que eu !ou
precisar fa&er com esse tipo de dado'7. ,oc poderia iniciar com as seguintes a%*es6
estabelecer um valor para as coordenadas! verificar sua igualdade com outro retIngulo!
verificar interse%&o com outro retIngulo e verificar se um determinado ponto est dentro
do retIngulo. .e voc precisa de um dado terreno! voc segue o mesmo processo e
inicia com fun%*es para carregar os dados do terreno! desen#ar o terreno! e assim por
diante. ,oc ent&o agrupa essas fun%*es junto com os dados. 1azer isso para cada tipo
de dado ue voc precisa no programa a essncia de programa%&o orientada a objeto.
) outra tcnica usada na abordagem orientada a objeto envolve treinar sua mente para
pensar em #ieraruia! do mais geral para o mais espec(fico. 0or e$emplo! uando
pensando sobre um objeto terreno! voc deve reparar as semel#an%as entre essa
estrutura de dados e uma lista. )final a descri%&o do terreno uma lista de coordenadas
carregada a partir de um aruivo. Uma lista um objeto genrico ue pode ser usado em
vrios pontos de vrios programas. )ssim! voc poderia criar uma classe genrica 9ista e
construir o objeto terreno a partir dela. HCs vamos e$aminar esse processo mais
detal#adamente a medida em ue vejamos outros e$emplos nos prC$imos tutoriais dessa
srie.
Classes
,amos usar um e$emplo espec(fico para consolidar algumas das ideias apresentadas na
li%&o anterior. Heste tutorial e$aminaremos um programa simples de lista de endere%os
implementado em C! verificando como tal programa pode ser convertido para C++ pela
adi%&o de classes.
6.4 Um programa 9ista de +ndere%os
6.5 Um programa em estilo antigo
6." 5efinindo uma classe
6.6 Um e$emplo mais simples
6.7 Uma classe retIngulo
6.8 Caracter(sticas espec(ficas das classes
6.4 A Um programa Zista de Endere*os
5igamos ue voc uer criar um programa 9ista de +ndere%os! ue maneje uma lista de
nomes e endere%os. ) primeira a%&o a tomar no sentido de criar o programa descrev-lo
em portugus. Uma boa descri%&o do programa em portugus vai ajud-lo a descobrir os
objetos ue comp*em o programa! por isso 'til uando se projeta programas em C++. )
descri%&o vai ajud-lo a ver uais os objetos ue precisar&o ser criados! bem como as
fun%*es ue dever&o ser implementadas para cada objeto. ,eja a seguinte descri%&o
t(pica6
Pg: 22 de 69.
(u quero criar um programa Lista de (ndereos) $ programa !ai manear uma lista
de nomes e de endereos) $ usurio do programa poder adicionar itens * lista,
e#ibir a lista no terminal e ainda procurar itens na lista)
,oc pode notar ue essa descri%&o muito geral! em alto n(vel. H&o menciona nada
sobre a interface com o usurio! leitura e armazenamento de informa%*es em disco!
verifica%&o de erros! formato dos registros! ou estrutura dos dados. /odos esses detal#es
de implementa%&o vir&o mais tarde. O ponto focal aui e$plorar a descri%&o
apresentada e ver o ue ela menciona. ) descri%&o fala de um ob$eto - uma lista - e de
um conjunto de a*Kes sobre esse objeto6 adicionar! e;ibir e procurar. ,amos avan%ar
com a descri%&o do programa6
+ lista pode ser carregada a partir de disco e arma&enada em disco) ,uando o
programa comear, ele !ai carregar a lista e e#ibir um menu que permite ao usurio
selecionar uma das seguintes opes- adicionar, e#cluir, procurar e encerrar a
e#ecuo do programa) ,uando o usurio selecionar (ncerrar, a lista ser sal!a em
disco e o programa terminar)
) partir dessa descri%&o voc pode ver ue # duas novas a*Kes sobre o ob$eto Zista6
carregar e sal'ar. ,oc pode notar tambm ue temos dois novos ob$etos a
desenvolver6 o ob$eto menu e o ob$eto programa. ) descri%&o menciona duas a*Kes
sobre o Senu6 apresentar e selecionar. O ob$eto programa tem! at o momento! trs
a*Kes6 iniciali=ar! apresentar menu! encerrar. $ principal aspecto a e#plorar nessa
descrio o fato de que um programa de aplicao se subdi!ide em obetos quase
que naturalmente. .a medida em !oc/ descre!e o programa !oc/ comea a !er os
obetos na descrio) $s obetos so normalmente os substanti!os usados na
descrio) 0oc/ tambm pode !er naturalmente as aes sobre os obetos, que so
normalmente os !erbos.
Uma boa tcnica para encontrar os objetos ue comp*em um programa descrever o
programa e ent&o fazer uma lista dos substantivos ue aparecem na descri%&o.
+liminando dessa lista as coisas obviamente e$ternas ao programa! como usurio!
terminal! etc. tem-se a lista dos objetos com os uais o programa ter ue lidar. 5a
mesma forma! fazendo uma lista dos verbos ue aparecem na descri%&o tem-se a lista
das a%*es sobre cada um dos objetos.
6.5 A Um programa em estilo antigo
Comecemos a cria%&o desse programa 9ista de +ndere%os pela implementa%&o em C.
+m seguida vamos migr-lo para C++ pela adi%&o de classes. O cCdigo seguinte mostra
uma implementa%&o bastante simples de 9ista de +ndere%os usando as fun%*es normais.
O programa pode adicionar elementos " lista! apresentar a lista no terminal e procurar um
item na lista. ) lista contida em uma matriz global.
7incl#de *iostrea(h6
7incl#de *string(h6

typede& str#ct
Pg: 23 de 69.
'
char nae[,0];
char city [,0];
char state[,0];
) addr@tr#ct;

const int :0;=10;
addr@tr#ct list[:0;];
int n#AnBist;

void addCae()
'
i& (n#AnBist * :0;)
'
co#t ** "Dnter CaeE ";
cin 66 list[n#AnBist](nae;
co#t ** "Dnter FityE ";
cin 66 list[n#AnBist](city;
co#t ** "enter @tateE ";
cin 66 list[n#AnBist](state;
n#AnBist++;
)
else
'
co#t ** "Bist &#ll+n";
)
)

void print<neCae(int i)
'
co#t ** endl;
co#t ** list[i](nae ** endl;
co#t ** list[i](city ** endl;
co#t ** list[i](state ** endl;
)

void printCaes()
'
int i;

&or (i=0; i * n#AnBist; i++)
print<neCae(i);
co#t ** endl;
)

void &indCae()
'
char s[,0];
int i;
int &o#nd=0;

i& (n#AnBist==0)
'
Pg: 24 de 69.
co#t ** "Bist epty+n";
)
else
'
co#t ** "Dnter nae to &indE ";
cin 66 s;
&or (i=0; i * n#AnBist; i++)
'
i& (strcp(s,list[i](nae)==0)
'
print<neCae(i);
&o#nd=1;
)
)
i& (G&o#nd)
co#t ** "Co atch+n";
)
)

void paint:en#()
'
co#t ** "0ddress list :ain :en#+n";
co#t ** " 1 ? add to list+n";
co#t ** " , ? print list+n";
co#t ** " - ? &ind nae+n";
co#t ** " . ? H#it+n";
co#t ** "Dnter choiceE ";
)

void ain()
'
char choice[10];
int done=0;
n#AnBist=0;
while (Gdone)
'
paint:en#();
cin 66 choice;
switch(choice[0])
'
case /1/E
addCae();
9reak;
case /,/E
printCaes();
9reak;
case /-/E
&indCae();
9reak;
case /./E
Pg: 25 de 69.
done=1;
9reak;
de&a#ltE
co#t ** "invalid choice(+n";
)
)
)
+sse programa tem estrutura e organiza%&o antigas e amplamente con#ecidas. )s
fun%*es s&o usadas para subdividir o cCdigo. - uma fun%&o para cada uma das op%*es
do menu! uma fun%&o apresenta o menu! e a fun%&o print@ne%ame contm um trec#o de
cCdigo redundante usado em dois pontos do programa. +sse programa demonstra os dois
principais usos de fun%*es no passado6 decomposi%&oFidentifica%&o de cCdigo e remo%&o
de redundIncia de codifica%&o.
- um problema fundamental com esse programa6 O cCdigo est altamente vinculado "
matriz global. Como se mostra no diagrama seguinte! a matriz global e referenciada
diretamente ao longo de todo o programa.
H&o # um modo simples de se modificar a solu%&o de matriz para uma outra estrutura
sem reescrever praticamente todo o cCdigo. O cCdigo ue implementa o programa - ue
contm portanto a solu%&o do problema - n&o tem porue se preocupar com a
organiza%&o f(sica da lista em uma matriz. O cCdigo para tratar a organiza%&o da lista na
matriz n&o deveria estar embutido no programa. +st no lugar errado.
) ideia subjacente " abstra%&o de dados proteger variveis globais! tais como uma
matriz global! da manipula%&o direta pelos programas de aplica%&o. Isolando! atravs de
c#amadas de fun%*es! as variveis ue implementam fisicamente a lista do restante do
programa! nCs podemos obter trs benef(cios6
muito mais fcil modificar a implementao da lista no futuro, porque apenas o
cdigo que trata especificamente da implementao da lista precisar ser alterado.
O programa fica melhor organizado porque os conceitos e regras inerentes lista
ficam separados do programa de aplicao, tanto quanto for poss!"el.
O cdigo espec!fico da implementao da lista pode ser usado em outros
programas de aplicao.
Pg: 26 de 69.
+m C! voc poderia fazer esse programa da seguinte forma6
7incl#de *iostrea(h6
7incl#de *string(h6

typede& str#ct
'
char nae[,0];
char city [,0];
char state[,0];
) addr@tr#ct;

%%???????? data and &#nctions &or the list ???????
const int :0;=10;
addr@tr#ct list[:0;];
int n#AnBist;

void listAnit()
'
n#AnBist=0;
)

void list8erinate()
'
)

int listI#ll()
'
i& (n#AnBist 6=:0;) ret#rn 1; else ret#rn 0;
)

int listDpty()
'
i& (n#AnBist==0) ret#rn 1; else ret#rn 0;
)

int list@i"e()
'
ret#rn n#AnBist;
)

int list0dd(addr@tr#ct addr)
'
i& (GlistI#ll())
'
list[n#AnBist++]=addr;
ret#rn 0; %% ret#rns 0 i& <=
)
ret#rn 1;
)

int listJet(addr@tr#ct1 addr, int i)
'
Pg: 27 de 69.
i& (i * list@i"e())
'
addr=list[i];
ret#rn 0; %% ret#rns 0 i& <=
)
ret#rn 1;
)
%%????????????????????????????????????????????????

void addCae()
'
addr@tr#ct a;

i& (GlistI#ll())
'
co#t ** "Dnter CaeE ";
cin 66 a(nae;
co#t ** "Dnter FityE ";
cin 66 a(city;
co#t ** "enter @tateE ";
cin 66 a(state;
list0dd(a);
)
else
co#t ** "Bist &#ll+n";
)

void print<neCae(addr@tr#ct a)
'
co#t ** endl;
co#t ** a(nae ** endl;
co#t ** a(city ** endl;
co#t ** a(state ** endl;
)

void printCaes()
'
int i;
addr@tr#ct a;

&or (i=0; i * list@i"e(); i++)
'
listJet(a,i);
print<neCae(a);
)
co#t ** endl;
)

void &indCae()
'
char s[,0];
int i;
int &o#nd=0;
Pg: 28 de 69.
addr@tr#ct a;

i& (list@i"e==0)
co#t ** "Bist epty+n";
else
'
co#t ** "Dnter nae to &indE ";
cin 66 s;
&or (i=0; i * list@i"e(); i++)
'
listJet(a, i);
i& (strcp(s,a(nae)==0)
'
print<neCae(a);
&o#nd=1;
)
)
i& (G&o#nd)
co#t ** "Co atch+n";
)
)

void paint:en#()
'
co#t ** "0ddress list :ain :en#+n";
co#t ** " 1 ? add to list+n";
co#t ** " , ? print list+n";
co#t ** " - ? &ind nae+n";
co#t ** " . ? H#it+n";
co#t ** "Dnter choiceE ";
)

void ain()
'
char choice[10];
int done=0;
listAnit();
while (Gdone)
'
paint:en#();
cin 66 choice;
switch(choice[0])
'
case /1/E
addCae();
9reak;
case /,/E
printCaes();
9reak;
case /-/E
&indCae();
9reak;
case /./E
Pg: 29 de 69.
done=1;
9reak;
de&a#ltE co#t ** "invalid choice(+n";
)
)
list8erinate();
)
Ho topo do programa # sete fun%*es! bem como as variveis usadas para implementar
fisicamente a lista. O objetivo dessas fun%*es proteger completamente! ou encapsular!
as variveis. Usando as fun%*es da lista! poss(vel fazer tudo o ue o programa precisa
fazer com a lista! sem usar diretamente ualuer das variveis reais da implementa%&o da
lista. )s fun%*es atuam como uma parede entre as variveis e o programa de aplica%&o.
Com essa estrutura de programa! ualuer altera%&o na implementa%&o da lista - por
e$emplo! modific-la de matriz para lista ligada - n&o tem ualuer impacto no programa
de aplica%&o! j ue apenas as sete fun%*es da lista teriam ue ser modificadas. )
estrutura desse programa mostrada a seguir.
)lgumas dessas fun%*es podem parecer irrelevantes! ou dispensveis. 0or e$emplo! a
fun%&o listNerminate n&o contm realmente ualuer cCdigo. +st presente no cCdigo
prevendo-se futuras necessidades. .e a implementa%&o for alterada de matriz para lista
ligada! vamos precisar de uma fun%&o para e$cluir todos os elementos da lista! para evitar
reten%&o de memCria n&o mais utilizada.
) fun%&o list&i=e contm apenas uma lin#a de cCdigo! mas se a lista for implementada
usando-se uma rvore binria! essa fun%&o ter ue percorrer toda a rvore
recursivamente para efetuar a contagem de seus elementos e! nesse caso! ser bem
maior ue a 'nica lin#a apresentada no programa acima.
O ue estamos fazendo aui pensar sobre todas as fun%*es ue poderiam ser
realmente necessrias para uma implementa%&o genrica da lista! sem nos limitarmos "
uma forma de implementa%&o f(sica da lista em particular.
Desmo ue a implementa%&o acima realize bem a miss&o de isolar a implementa%&o da
lista do restante do programa de aplica%&o! ela tem ainda alguns problemas. 0or e$emplo!
ualuer um pode alterar o programa! passando a utilizar diretamente as variveis da
Pg: 30 de 69.
implementa%&o da lista! como ue ignorando a parede de isolamento composta pelas
fun%*es da lista. +m outras palavras! n&o # ualuer obrigatoriedade de se utilizar as
fun%*es da lista. Dais ainda! n&o ser muito fcil utilizar-se duas listas em um mesmo
programa de aplica%&o. /odas as fun%*es da lista s&o dependentes da e$istncia de uma
'nica matriz. ,oc pode pensar em solucionar esse problema passando a matriz como
um parImetro para as fun%*es! mas essa alternativa vai se mostrar muito confusa. C++
resolve esses problemas com o recurso de classes.
6." A De<inindo uma classe
O cCdigo seguinte toma os dados e as sete fun%*es da implementa%&o da lista do
programa anterior! e os implementa como uma classe C++ e usa essa classe no
programa de aplica%&o.
7incl#de *iostrea(h6
7incl#de *string(h6

typede& str#ct
'
char nae[,0];
char city [,0];
char state[,0];
) addr@tr#ct;

const int :0; = 10;

class Bist
'
addr@tr#ct list[:0;];
int n#AnBist;
p#9licE
Bist()E n#AnBist(0) %% constr#ctor
'
)
KBist() %% destr#ctor
'
)
int I#ll()
'
i& (n#AnBist 6=:0;) ret#rn 1; else ret#rn 0;
)
int Dpty()
'
i& (n#AnBist==0) ret#rn 1; else ret#rn 0;
)
int @i"e()
'
ret#rn n#AnBist;
)
int 0dd(addr@tr#ct addr)
'
i& (GI#ll())
Pg: 31 de 69.
'
list[n#AnBist++]=addr;
ret#rn 0; %% ret#rns 0 i& <=
)
ret#rn 1;
)
int Jet(addr@tr#ct1 addr, int i)
'
i& (i * @i"e())
'
addr=list[i];
ret#rn 0; %% ret#rns 0 i& <=
)
ret#rn 1;
)
);
%%???????????????????????????????????????????????

Bist list;

void addCae()
'
addr@tr#ct a;

i& (Glist(I#ll())
'
co#t ** "Dnter CaeE ";
cin 66 a(nae;
co#t ** "Dnter FityE ";
cin 66 a(city;
co#t ** "enter @tateE ";
cin 66 a(state;
list(0dd(a);
)
else
co#t ** "Bist &#ll+n";
)

void print<neCae(addr@tr#ct a)
'
co#t ** endl;
co#t ** a(nae ** endl;
co#t ** a(city ** endl;
co#t ** a(state ** endl;
)

void printCaes()
'
int i;
addr@tr#ct a;

&or (i=0; i * list(@i"e(); i++)
'
Pg: 32 de 69.
list(Jet(a,i);
print<neCae(a);
)
co#t ** endl;
)

void &indCae()
'
char s[,0];
int i;
int &o#nd=0;
addr@tr#ct a;

i& (list(@i"e()==0)
co#t ** "Bist epty+n";
else
'
co#t ** "Dnter nae to &indE ";
cin 66 s;
&or (i=0; i * list(@i"e(); i++)
'
list(Jet(a, i);
i& (strcp(s,a(nae)==0)
'
print<neCae(a);
&o#nd=1;
)
)
i& (G&o#nd)
co#t ** "Co atch+n";
)
)

void paint:en#()
'
co#t ** "0ddress list :ain :en#+n";
co#t ** " 1 ? add to list+n";
co#t ** " , ? print list+n";
co#t ** " - ? &ind nae+n";
co#t ** " . ? H#it+n";
co#t ** "Dnter choiceE ";
)

int ain()
'
char choice[10];
int done=0;

while (Gdone)
'
paint:en#();
cin 66 choice;
switch(choice[0])
Pg: 33 de 69.
'
case /1/E
addCae();
9reak;
case /,/E
printCaes();
9reak;
case /-/E
&indCae();
9reak;
case /./E
done=1;
9reak;
de&a#ltE
co#t ** "invalid choice(+n";
)
)
ret#rn 0;
%% list destroys itsel& when it goes o#t o& scope(
)
) classe lista est definida prC$imo ao topo do programa e come%a com as palavras class
Zist. Isso como uma declara%&o de tipo6 a instIncia real de lista aparece na lin#a
9ist listT
+ssa lin#a declara uma varivel denominada list do tipo class Zist.
Gepare ue a classe Zist inicia-se de modo muito semel#ante a uma estrutura. +la
declara duas variveis do mesmo modo ue se faria em uma declara%&o de estrutura.
+ssas variveis s&o denominadas dados membro.
+m continua%&o! a defini%&o da classe contem a palavra public. +ssa palavra indica ue
as fun%*es seguintes poder&o ser invocadas por ualuer cCdigo ue use essa classe. O
termo de sentido oposto pri'ate! e usado uando fun%*es ou dados devem
permanecer ocultos dentro da classe! in"is!"eis a ualuer cCdigo ue use a classe.
)s variveis e fun%*es definidas dentro de uma classe s&o! por default! pri'ate a menos
ue voc e$plicitamente as fa%a public.
)pCs a defini%&o dos dados membro vem a defini%&o das <un*Kes membro. 1o essas
as funes que podem ser aplicadas *s inst2ncias da classe. )s primeiras duas
fun%*es em nosso e$emplo - Zist e [Zist - tem um significado 'nico. .&o denominadas
construtor e destrutor! respectivamente.
$ construtor chamado automaticamente sempre e quando passa a e#istir uma
inst2ncia da classe. Hesse caso! uma instIncia da classe Zist passa a e$istir logo ue
se inicia o programa porue est declarada como uma varivel global! mas nem sempre
as instIncias de uma classe s&o declaradas como variveis globais. +nt&o! como regra! o
construtor c#amado automaticamente uando uma instIncia da classe passa a e$istir! e
os construtores de pointers so ati!ados quando new chamado para o pointer) $
construtor tem o mesmo nome da classe-
Pg: 34 de 69.
Bist()E n#AnBist(0) %% constr#ctor
'
)
) inicializa%&o do dado membro numIn9ist 'nica nesse caso. Um outro modo de se
fazer isso
Bist() %% constr#ctor
'
n#AnBist = 0;
)
) primeira forma ! no entanto! mais eficiente em tempo de e$ecu%&o! devido " maneira
como o C++ internamente inicializa as classes. ) sinta$e! uando usada como mostrada
nesse construtor! inicializa o dado membro numIn9ist atribuindo-l#e o valor E 8zero? e
deve ser usada sempre ue se inicializa dados membro em um construtor.
$ destrutor - [Zist em nosso e#emplo - chamado automaticamente quando se
encerra o escopo dentro do qual a inst2ncia da classe foi declarada, que onde a
inst2ncia ento e#clu3da. 5estrutores s&o 'nicos! rigidamente limitados "s variveis da
classe! e podem referenciar variveis da classe em ualuer momento.
) varivel list uma instIncia da classe 9ist. .e list fosse uma estrutura unidimensional
seria declarada de modo semel#ante ao ue foi declarada em nosso e$emplo! e
funcionaria da mesma maneira.
+ !ari!el list to grande quanto o tamanho de seus dados membro. )s fun%*es!
em realidade! n&o ocupam ualuer espa%o f(sico nas instIncias da classe. ) sinta$e da
linguagem apenas permite ue sejam declaradas! e usadas! com instIncias da classe!
mas n&o as implementa fisicamente a cada instIncia da classe.
) instIncia list usada ao longo de todo o programa. ) cada vez ue algo precisa ser
feito com list voc encontra o nome da instIncia seguido de um ponto e do nome da
fun%&o. 5e novo! essa nota%&o segue a sinta$e usada para estruturas. O ponto significa
chame a funo membro da classe Zist para a inst2ncia espec3fica list.
Isso pode n&o fazer sentido imediatamente para voc. )inda assim! tudo oM. O aspecto
importante a ser e$tra(do desse e$emplo ue tudo o ue fizemos foi tomar alguns dados
- nesse caso! uma matriz e um inteiro - e as fun%*es necessrias para manipular essas
variveis! e colocamos tudo junto dentro dos limites de uma classe. )gora as variveis
n&o podem ser acessadas diretamente pelo restante do cCdigo! pelo cCdigo e$terno "
classe. 5evido ao fato de serem membros privados da classe! somente podem ser
acessados por fun%*es membro da classe! e n&o por ualuer outra parte do cCdigo! n&o
pertencente a classe. O objeto list - dados e fun%*es se fundem em objeto - podem ser
acessados e$clusivamente via fun%*es membro.
6.6 A Um e;emplo mais simples
O 'ltimo e$emplo talvez ten#a sido muito grande. ,amos e$aminar a classe &tacH para
revisar alguns conceitos em um e$emplo menor.
Pg: 35 de 69.
7incl#de *iostrea(h6

class @tack
'
int stk[100];
int top;
p#9licE
@tack()E top(0) ')
K@tack() ')
void Flear() 'top=0;)
void L#sh(int i) 'i& (top * 100) stk[top++]=i;)
int Lop()
'
i& (top 6 0) ret#rn stk[??top];
else ret#rn 0;
)
int @i"e() 'ret#rn top;)
);

int ain()
'
@tack stack1, stack,;

stack1(L#sh(10);
stack1(L#sh(,0);
stack1(L#sh(-0);
co#t ** stack1(Lop() ** endl;
stack,=stack1;
co#t ** stack,(Lop() ** endl;
co#t ** stack,(Lop() ** endl;
co#t ** stack1(@i"e() ** endl;
co#t ** stack,(@i"e() ** endl;
ret#rn 0;
)
+sse programa consiste de duas partes6 a classe &tacH e a fun%&o principal main. )
classe define o tipo &tacH! e duas instIncias desse tipo s&o declaradas dentro de main.
Cada uma das instIncias vai ter a sua prCpria cCpia dos dados membro stH e top! e a
opera%&o si=eo< para cada uma delas indicaria e$atamente o espa%o necessrio 8QE< ou
<E< b:tes! dependendo do ambiente? alocado para cada uma. 4ma classe usa tanto
espao em mem"ria quanto uma estrutura usaria para os mesmos dados membro)
.o h acrscimo de mem"ria pela e#ist/ncia de funes membro.
) classe contm um construtor! um destrutor e uatro outras fun%*es! e cada uma delas
public. 0orue as fun%*es s&o p'blicas! elas podem ser c#amadas por ualuer instIncia
da classe. O construtor c#amado uando as variveis de stacH s&o instanciadas! e o
destrutor c#amado uando se encerra o escopo em ue essas variveis foram criadas.
5entro da fun%&o main! diferentes c#amadas s&o feitas para as outras uatro fun%*es
membro da classe! usando o nome da instIncia seguido por um ponto e pelo nome da
fun%&o. 0or e$emplo6
stack1(L#sh(10);
Pg: 36 de 69.
+ssa lin#a indica ue o valor 40 deve ser colocado em stacH4. ) instIncia stacH4 contm
dois itens de dados 8stH e top? os uais contem valores. +ssa lin#a significa chame a
funo Push para a estrutura contida em para a estrutura contida em para a
estrutura contida em para a estrutura contida em para a estrutura contida em para a
estrutura contida em para a estrutura contida em stacH4, e#ecute os comandos da
funo Push, atribuindo o !alor 56 para o elemento da matri& e para o inteiro
contido dentro de stacH4. - duas &tacHs completamente separadas nesse programa6
stacH4 e stacH5. Um comando como stacH5.PushE7F significa ue 7 deve ser colocado
na estrutura stacH5.
@ interessante e$aminar o comando de atribui%&o colocado na metade na fun%&o main.
+sse comando faz o ue faria um comando de atribui%&o entre duas estruturas6 os valores
dos dados membro da instIncia " direita do comando s&o copiados para os dados
membro da instIncia a esuerda.
stack, = stack1;
)pCs a e$ecu%&o do comando! as duas &tacHs contem os mesmos valores. Isso
normalmente funciona bem! mas se ualuer dos dados membro for um pointer voc
precisa ter certos cuidados. ,amos ver um bom e$emplo desse problema no
/utorial 3.
6.7 A Uma classe retYngulo
Como voc decide o ue deve! e o ue n&o deve! ser implementado sob a forma de
objetoA
+ssencialmente o ue voc faz tomar em conjunto cada peueno grupo de elementos
de dados inter-relacionados ue voc encontra no programa! ane$ar algumas fun%*es ao
conjunto e definir uma classe. Ho e$emplo anterior - classe &tacH! a matriz stH e o inteiro
top s&o os elementos de dados necessrios para implementar a pil#a. )s fun%*es
relacionadas a esse peueno grupo de dados s&o Push! Pop! Clear e &i=e. Vuntando-se
os dados e as fun%*es obtem-se uma classe.
5igamos ue voc precise armazenar as coordenadas para um retIngulo em um de seus
programas. .uas variveis s&o denominadas ;4! J4! ;5 e J5. T4 e J4 representam o
canto superior esuerdo! e ;5 e J5 representam o canto inferior direito. +ssas uatro
variveis juntas representam um retIngulo. Buais s&o as fun%*es 'teis a implementar
junto com essas variveisA ,oc precisa inicializar as variveis 8um trabal#o perfeito para
o construtor?! e talvez precise ter meios de encontrar o per(metro e a rea do retIngulo. )
classe poderia se implementada como no e$emplo seguinte6
class Mect
'
int !1, y1, !,, y,;
p#9licE
Mect(int le&t=0,int top=0,
int right=0,int 9otto=0)E
!1(le&t), y1(top), !,(right), y,(9otto)
Pg: 37 de 69.
'
)
KMect() ')
int Neight() ' ret#rn (y,?y1); )
int Oidth() ' ret#rn (!,?!1); )
int 0rea() ' ret#rn Oidth()$Neight(); )
int Lerieter() ' ret#rn ,$Oidth()+,$Neight();)
);
.e voc apenas e$aminar o programa ue estiver desenvolvendo! e tentar identificar cada
agrupamento natural de dados! e as fun%*es 'teis ue manipulam esses grupos de
dados! voc j estar dando um grande passo na dire%&o de implementar seu programa
de modo orientado a objetos
6.8 A Caracter1sticas espec1<icas das classes
,amos rever algumas das caracter(sticas espec(ficas das classes aprendidas neste
tutorial.
+m primeiro lugar! cada classe tem um construtor e um destrutor. O construtor
c#amado uando uma instIncia da classe passa a e$istir! e o destrutor c#amado
uando a instIncia destru(da! ue normalmente o ponto do programa em ue se
encerra o escopo dentro do ual a instIncia da classe foi criada. O e$emplo seguinte
poder ajud-lo a aprender um pouco mais sobre construtores e destrutores6
7incl#de *iostrea(h6

class @aple
'
int n#;
p#9licE
@aple(int i)E n#(i)
'
co#t ** "constr#ctor " ** n#
** " called" ** endl;
)
K@aple()
'
co#t ** "destr#ctor " ** n#
** " called" ** endl;)
);

int ain()
'
@aple $sp;
@aple s(1);

co#t ** "line 1" ** endl;
'
@aple tep(,);
co#t ** "line ," ** endl;
)
Pg: 38 de 69.
co#t ** "line -" ** endl;
sp = new @aple(-);
co#t ** "line ." ** endl;
delete sp;
co#t ** "line 3" ** endl;
ret#rn 0;
)
Com papel e lpis! siga em sua mesa! passo a passo! a e$ecu%&o desse cCdigo e tente
predizer o ue vai acontecer em uma e$ecu%&o real. 5epois e$ecute esse mesmo cCdigo
com uma ferramenta de debug na modalidade singleAetepping e veja o ue acontece
5ados membro e fun%*es membro podem ser public ou pri'ate! dependendo de como
ten#am sido definidos dentro do programa. + melhor regra, para preser!ar os
benef3cios da orientao a obetos, e no usar dados membro public. Um dado
membro public pode ser acessado a partir de ualuer ponto do programa! enuanto os
dados membro pri'ate somente podem ser acessados pelas fun%*es membro da classe.
,amos modificar um pouco a classe \ect para ver o ue acontece.
class Mect
'
int !1, y1, !,, y,;
p#9licE
Mect(int le&t=0,int top=0,
int right=0,int 9otto=0)E
!1(le&t), y1(top), !,(right), y,(9otto)
'
)
KMect() ')
privateE
int Neight() ' ret#rn (y,?y1); )
int Oidth() ' ret#rn (!,?!1); )
p#9licE
int 0rea() ' ret#rn Oidth()$Neight(); )
int Lerieter() ' ret#rn ,$Oidth()+,$Neight();)
);
)gora as fun%*es 0idth e ]eigth s&o pri'ate. +las podem ser c#amadas como
mostradas aui porue Area e Perimeter s&o fun%*es membro. Das se voc tentar
Mect r;
(((
co#t ** r(Neight();
voc vai incorrer em um erro de compila%&o porue ]eigth uma fun%&o pri'ate.
)tribui%&o entre duas instIncias de uma mesma classe simplesmente copia os dados
membro de uma instIncia para a outra. 0or e$emplo6
)tribui%&o entre duas instIncias de uma mesma classe simplesmente copia os dados
membro de uma instIncia para a outra. 0or e$emplo6
Pg: 39 de 69.
Mect r1,r,;
(((
r1=r,;
o mesmo ue
r1(!1 = r,(!1;
r1(y1 = r,(y1;
r1(!, = r,(!,;
r1(y, = r,(y,;
1inalmente! # dois modos aceitveis de se especificar fun%*es membro. Os e$emplos
mostrados anteriormente nesse tutorial representam um dos mtodos! denominado
fun%*es inline. O cCdigo a seguir mostra o segundo mtodo! aplicado na classe \ect6
class Mect
'
int !1, y1, !,, y,;
p#9licE
%% the constr#ctor #ses de&a#lt para( @ee t#tor ,
Mect(int le&t=0,int top=0,
int right=0,int 9otto=0);
KMect();
int Neight();
int Oidth();
int 0rea();
int Lerieter();
);

MectEEMect(int le&t, int top, int right, int 9otto)E
!1(le&t), y1(top), !,(right), y,(9otto)
%% de&a#lt val#es are #nderstood &ro the prototype
'
)
MectEEKMect()
'
)

int MectEENeight()
'
ret#rn (!,?!1);
)

int MectEEOidth()
'
ret#rn (y,?y1);
)

int MectEE0rea()
'
Pg: 40 de 69.
ret#rn Oidth()$Neight();
)

int MectEELerieter()
'
ret#rn ,$Oidth()+,$Neight();
)
+ssa 'ltima forma normalmente mais fcil de se ler uando as fun%*es da classe s&o
e$tensas. ) nota%&o \ect:: especifica a classe a ual a fun%&o pertence. O cCdigo de
defini%&o da classe contm basicamente os protCtipos das fun%*es membro da classe.
- vrias outras coisas ue voc pode fazer uando usa classes! mas o material
apresentado aui contm as li%*es suficientes para ue voc crie abstra%*es de dados
simples! e as correspondentes fun%*es para assim definir classes. )gora j podemos
iniciar a cria%&o de hierar)uia de classes.
]eran*a
7.0 M Introdu*+o
5igamos ue voc j implementou uma lista de classes! e ue agora deseja modific-las.
Ho vel#o mundo da programa%&o voc tomaria o cCdigo fonte de cada classe e come%aria
a alter-los. Ho mundo da programa%&o orientada a objeto voc faz as coisas de modo
bem diferente. ,oc dei$a as classes e$istentes inalteradas! dei$a o cCdigo fonte j
implementado tal como est! e aplica as suas altera%*es sobre a implementa%&o atual!
usando um processo denominado heran*a.
) aplica%&o de altera%*es atravs de #eran%a nos leva a um dos pontos centrais da
programa%&o orientada a objeto. /rata-se de um modo totalmente diferente de se
modificar programas e$istentes! mas traz vrios e importantes benef(cios6
.upon#a ue voc est usando uma classe desenvolvida por terceiros! e ue voc
n&o tem o cCdigo fonte. Com o mecanismo de #eran%a voc dei$a a classe
e$istente intocada e como ue assenta suas altera%*es sobre ela! sem
necessidade de con#ecer o cCdigo fonte original.
) implementa%&o original da classe est - de se esperar - completamente testada
e isenta de bugs. .e voc modificasse o cCdigo fonte original! todo o esfor%o de
testes teria ue ser repetido. )ltera%*es sobre cCdigo e$istente podem incorrer em
efeitos secundrios indesejveis! n&o percebidos imediatamente. )comodando
suas altera%*es sobre a classe e$istente! voc preserva o cCdigo original livre de
erros! e apenas o cCdigo da altera%&o precisa ser testado.
O processo de assentar altera%*es sobre cCdigo e$istente nos for%a a pensar no
sentido do mais genrico para o mais espec(fico. ,oc implementa uma classe
genrica e posteriormente assenta sobre ela altera%*es para tratar situa%*es
espec(ficas. Um gan#o interessante dessa abordagem o fato de ue classes
genricas podem ser reutilizadas em vrios e diferentes programas. Cada novo
programa assenta altera%*es sobre a classe original! mas esta permanece a
Pg: 41 de 69.
mesma em todos os programas onde for utilizada.
.e a classe base for otimizada! todas as classes constru(das sobre ela recebem os
benef(cios dessa otimiza%&o! sem ualuer modifica%&o nos programas. 0or
e$emplo! supon#a ue uma determinada classe Zist foi otimizada e agora e$ecuta
uma classifica%&o de elementos =E vezes mais rpido ue em sua primeira vers&o.
/odas as classes constru(das a partir da classe Zist v&o e$ecutar classifica%&o de
elementos =E vezes mais rpido! sem ualuer modifica%&o adicional em
programas.
+sses s&o os benef(cios ue normalmente entusiasmam as pessoas com programa%&o
orientada a objeto.
7.4 A Um e;emplo
,amos e$aminar um e$emplo espec(fico para percebermos como a #eran%a funciona.
.upon#a ue voc comprou um gerenciador de listas! ue tem as #abilidades de inserir
elementos em uma localiza%&o determinada! resgatar itens da lista e informar o taman#o
da lista. O cCdigo da classe Zist mostrado a seguir! juntamente com um peueno trec#o
de cCdigo para teste.
7incl#de *iostrea(h6

class Bist
'
int array[100];
int co#nt;
p#9licE
Bist()E co#nt(0) ')
KBist() ')
void Ansert( int n, int location )
'
int i;
&or (i=co#nt; i 6= location; i??)
array[i+1] = array[i];
array[location]=n;
co#nt++;
)
int Jet( int location ) 'ret#rn array[location];)
int @i"e() ' ret#rn co#nt; )
);

void ain()
'
Bist list;
int i, val#e;

&or (i=0; i * 10; i++)
list(Ansert(i,i);
list(Ansert(100,3);
list(Ansert(,00,P);
list(Ansert(-00,0);
&or (i=0; i * list(@i"e(); i++)
Pg: 42 de 69.
co#t ** list(Jet(i) ** endl;
)
) classe contm uma peuena rotina de verifica%&o de erros! obviamente essa rotina teria
ue ser ampliada se este fosse um produto com fins comerciais.
.upon#a agora ue voc uer fazer duas modifica%*es nessa classe! para adicionar dois
novos recursos.
0rimeiramente! voc uer uma fun%&o de inser%&o classificada! de tal modo ue apCs a
inser%&o a classe manten#a a lista classificada corretamente.
+m segundo lugar! voc uer manter atualizada a soma total dos valores dos itens ue
comp*es a lista. )o invs de percorrer toda a lista efetuando a totaliza%&o a cada vez ue
a fun%&o soma for c#amada! voc uer ue a soma total seja atualizada a cada inser%&o
de novo item.
Obviamente voc poderia simplesmente modificar o cCdigo da classe Zist mostrado
anteriormente. (m 788 !oc/ usa herana ao in!s de modificar o c"digo e#istente.
,amos criar uma classe &ortedZist #erdando a classe Zist e assentando sobre ela as
nossas modifica%*es. Comecemos por adicionar a capacidade de inser%&o classificada.
class @ortedBistE p#9lic Bist
'
p#9licE
@ortedBist()EBist() ')

@ortedAnsert(int n)
'
int i,5;

i=0;
do
'
5 = Jet(i);
i& (5 * n ) i++;
) while (5 * n 11 i * @i"e());
Ansert(n, i);
)
);
) classe Zist original permanece totalmente inalterada. ."s simplesmente criamos a
classe &ortedZist sobre a classe List. ) classe .orted9ist #erda o comportamento da
classe 9ist! ou seja! a classe &ortedZist uma classe deri'ada da classe Zist. ) classe
Zist a classe base para &ortedZist.
) classe 9ist #erdada na primeira lin#a de cCdigo de &ortedZist6
class @ortedBistE p#9lic Bist
Os dois pontos 8 : ? apCs &ortedZist indicam ue ueremos usar o mecanismo de
#eran%a. O termo public indica ue ueremos ue as fun%*es e variveis public na
classe Zist permane%am public na classe &ortedZist. +m lugar do termo public!
poder(amos optar por pri'ate ou protected. +m ualuer desses casos todas as
Pg: 43 de 69.
variveis e fun%*es p'blicas da classe base seriam convertidas para a classe derivada. O
uso de public nesses casos o padr&o. O diagrama seguinte ilustra o ue acontece.
) classe &ortedZist simplesmente estende! amplia as capacidades da classe Zist.
Bualuer um ue use a classe &ortedZist tem acesso tanto "s fun%*es de Zist uanto "s
novas fun%*es de &ortedZist.
O construtor de &ortedZist tambm tem um formato novo. Usamos o sinal de dois pontos
8 : ? para c#amar o construtor da classe base.
@ortedBist()EBist() ')
+ssa lin#a significa ue o construtor denominado Zist da classe base deve ser c#amado!
e ue construtor de &ortedZist n&o tem nada a fazer.
Ho restante do cCdigo da classe &ortedZist nCs simplesmente adicionamos a nova
fun%&o &ortedInsert " classe. +ssa nova fun%&o faz uso das fun%*es originais Insert! ^et
e &i=e pertencentes " classe Zist! mas n&o acessa diretamente nen#um dado membro da
classe Zist! at porue n&o poderia. Gepare ue os dados membro da classe Zist s&o
pri'ate e portanto podem ser acessados e$clusivamente por fun%*es membro da classe
Zist. .&o in!is3!eis " classe derivada.
.upon#a ue voc ueira ter uma varivel ou uma fun%&o ue pare%a pri'ate para
usurios e$ternos! mas se comporte como public para a classe derivada. 0or e$emplo!
digamos ue a classe &ortedZist precise acessar diretamente a matriz contida em Zist
para mel#or performance! mas ainda desejamos impedir ue os programas de aplica%&o!
usurios de Zist ou de &ortedZist! acessem diretamente a matriz. 0odemos fazer isso
usando protected:! onde usamos public: ou pri'ate: 5eclarando ue a matriz um
membro protected na classe Zist! nCs a tornamos acess(vel pelas classes derivadas de
Pg: 44 de 69.
Zist! mas n&o pelas instIncias normais de Zist ou de &ortedZist.
)gora vamos adicionar a capacidade de totaliza%&o " classe &ortedZist. 0ara isso vamos
precisar de uma nova varivel! e vamos ainda precisar modificar o comportamento da
fun%&o de inser%&o! para ue esta passe a atualizar a soma total. O cCdigo necessrio
para essa implementa%&o mostrado a seguir.
class @ortedBistE p#9lic Bist
'
privateE
int total;
p#9licE
@ortedBist()EBist(), total(0) ')
void Ansert( int n, int location )
'
total = total + n;
BistEEAnsert(n, location);
)
int Jet8otal() ' ret#rn total; )
@ortedAnsert(int n)
'
int i,5;
i=0;
do
'
5 = Jet(i);
i& (5 * n ) i++;
) while (5 * n 11 i * @i"e());
Ansert(n, i);
)
);
Hessa nova vers&o da classe &ortedZist! nCs acrescentamos um novo dado membro
denominado total! uma nova fun%&o membro de nome ^etNotal para resgatar o total
atual! e ainda uma nova fun%&o Insert que se sobrepe * funo Insert original.
Dodificamos o construtor de &ortedZist ue passa a inicializar a varivel total.
)gora! sempre ue a classe &ortedZist for utilizada e a fun%&o Insert for invocada! a
nova vers&o da fun%&o Insert ser ativada! ao invs da vers&o original ue permanece
inalterada dentro da classe Zist. Isso vale inclusive para a fun%&o &ortedInsert da classe
&ortedZist. Buando a fun%&o &ortedInsert c#ama a fun%&o Insert! a nova fun%&o Insert
ativada.
O cCdigo da nova fun%&o Insert simples e de compreens&o uase automtica6
void Ansert( int n, int location )
'
total = total + n;
BistEEAnsert(n, location);
)
+ssa fun%&o primeiramente adiciona o novo valor ao conte'do atual da varivel total.
5epois c#ama a vers&o original da fun%&o Insert! #erdada da classe base! ue processa
Pg: 45 de 69.
a inser%&o no novo valor na lista. ) nota%&o Zist:: determina a classe! dentro da
#ieraruia de classes! a ue pertence a fun%&o Insert ue deve ser invocada. +m nosso
e$emplo # uma #ieraruia simples! de apenas dois n(veis - a classe base e uma classe
derivada - o ue torna simples a decis&o sobre ue classe usar. Das em uma #ieraruia
com vrios n(veis! vrias camadas de #eran%a! essa tcnica deve ser usada para se
e$plicitar o classe ue contm a vers&o da fun%&o ue se uer invocar.
9 essa acomodao de alteraes em camadas atra!s do mecanismo de herana,
e a habilidade de se pensar e trabalhar com m:ltiplos n3!eis de herana, como
mostrado aqui, que d ao 788 um sentido tridimensional)
7.5 A Um e;emplo mais a'an*ado
,amos usar o ue aprendemos sobre #eran%a at agora para criar um e$emplo mais
realista.
O ue ueremos fazer criar uma classe para um novo tipo numrico denominado inteiro
de m?ltipla precis+o ou! abreviadamente! mint. +sse novo tipo inteiro vai operar de
modo semel#ante ao inteiro normal! mas poder conter at =EE d(gitos 8por enuanto -
mais adiante vamos ver como estender um n'mero para ter tantos d(gitos uantos
possam ser armazenados em memCria! usando listas ligadas?. Um n'mero do tipo mint
permite ue se fa%a opera%*es tais como calcular o valor de 2EW 8fatorial de 2E? ou
encontrar o >EE
X
valor em uma seuncia 1ibonacci.
Bual a boa norma de se criar novas classes em um ambiente de programa%&o orientada a
objetoA
Uma boa norma pensar no sentido do mais genrico para o mais espec(fico. 0or
e$emplo! o ue um inteiro de m'ltipla precis&oA @ apenas uma lista de d(gitos. 0ortanto!
voc pode criar uma classe genrica para manejar uma lista! com todas as capacidades
de inser%&o de elementos na lista necessrias para controlar uma seuncia de d(gitos! e
ent&o acrescentar a essa classe os recursos necessrios para implementar um n'mero
mint.
Como vamos escol#er os recursos necessrios " nossa listaA
Uma boa forma pensar sobre o ue vamos ter ue fazer com os d(gitos em opera%*es
mint t(picas. )lternativamente voc poderia pegar uma classe Zist j e$istente e construir
a solu%&o sobre ela. ,amos usar a primeira abordagem - criar uma classe Zist - j ue
n&o dispomos de uma boa classe Zist para utilizar.
Como voc inicializa mintA O mint se inicia sem conter ualuer d(gito significativo.
,amos inserir um d(gito por vez para criar um n'mero mint. 0ara o valor <.Q2P o mint vai
se parecer com o seguinte6
Cada uadrado nesse diagrama representa um elemento na lista! e cada elemento da
lista contm um valor inteiro entre E e P. 0recisamos da #abilidade de inserir d(gitos ao
in(cio ou ao fim da lista! dependendo de onde ven#a o valor inicial.
Pg: 46 de 69.
,amos e$aminar uma adi%&o! como mostrado na figura seguinte6
0ara implementar adi%&o nCs vamos precisar come%ar o processamento resgatando o
'ltimo d(gito de cada um dos dois n'meros mint a serem somados! somar esses d(gitos e
ent&o inserir o d(gito resultante no novo n'mero mint ue conter o resultado da soma.
+m seguida vamos tomar os dois d(gitos " esuerda dos 'ltimos d(gitos somados e repetir
a mesma opera%&o! e assim por diante.
+st claro ue vamos precisar de um modo eficiente de nos deslocarmos do final para o
in(cio da lista 8por e$emplo! fun%*es ^etZast e ^etPre'ious?! e vamos tambm precisar
de um recurso ue nos avise ue atingimos o in(cio da lista 8talvez um valor de retorno de
^etPre'ious possa indicar ue a a%&o n&o mais poss(vel! ou uma fun%&o &i=e possa
indicar at onde podemos nos deslocar?.
/endo em mente todas as nossas discuss*es e e$emplos anteriores com listas! podemos!
resumidamente! concluir ue a nossa nova classe Zist precisar ter as seguintes
capacidades6
Construtor e destrutor
)dd/o1ront
)dd/o+nd
Yet1irst
Yet9ast
Yet0revious
YetHe$t
.ize
Clear
O cCdigo mostrado a seguir implementa a classe Zist6
class Bist
'
int array[100];
int co#nt;
int pointer;
p#9licE
Bist()E co#nt(0), pointer(0) ')
KBist() ')
void 0dd8oIront(int n)
'
int i;
&or(i=co#nt; i 6= 1; i??)
Pg: 47 de 69.
array[i]=array[i?1];
array[0]=n;
co#nt++;
)
void 0dd8oDnd(int n)
'
array[co#nt++]=n;
)
%% 1n is a re&erence ? see t#tor ,
int JetIirst(int 1 n)
'
i& (co#nt==0)
ret#rn 1;
else
'
n=array[0];
pointer=0;
ret#rn 0;
)
)
int JetBast(int 1 n)
'
i& (co#nt==0)
ret#rn 1;
else
'
n=array[co#nt?1];
pointer=co#nt?1;
ret#rn 0;
)
)
int JetLrevio#s(int 1 n)
'
i& (pointer?1 * 0)
ret#rn 1;
else
'
pointer??;
n=array[pointer];
ret#rn 0;
)
)
int JetCe!t(int 1 n)
'
i& (pointer+1 6 co#nt?1)
ret#rn 1;
else
'
pointer++;
n=array[pointer];
ret#rn 0;
)
)
Pg: 48 de 69.
int @i"e() ' ret#rn co#nt; )
void Flear() ' co#nt = 0; )
);
) essa altura! esse cCdigo j deve ser facilmente compreens(vel por voc.
Zist simplesmente uma lista genrica de n'meros inteiros. Um dado membro
denominado pointer aponta para um dos elementos da lista e atualizado pelas uatro
fun%*es ^et.... Cada uma dessas fun%*es retorna E para indicar ue a opera%&o foi bem
sucedida! ou = para indicar insucesso na opera%&o. 0or e$emplo! se pointer n&o aponta
para o elemento E da lista 8o elemento mais a esuerda?! ent&o ainda # elementos a
esuerda do elemento apontado! e a fun%&o ^etPre'ious vai retornar E?. )s duas
fun%*es Add.... realizam soma no in(cio e no fim da lista. Ha vers&o atual! essas fun%*es
n&o possuem cCdigo para verifica%&o de erros.
) fun%&o AddNoPront contm uma ineficincia intr(nseca! porue a cada inser%&o ela
desloca todo o conte'do da matriz uma posi%&o para bai$o.
) classe Sint #erda a classe Zist e a utiliza para construir o tipo numrico mint. ) classe
Sint implementa dois construtores6 um construtor default ue n&o recebe ualuer
parImetro! e um segundo construtor ue recebe um string e o utiliza para preenc#er a
lista. Implementa ainda as fun%*es para somar e para imprimir dois n'meros mint. O
cCdigo mostrado a seguir6
class :intE p#9lic Bist
'
p#9licE
:int()EBist() ')
:int(char $s)EBist()
'
char $p;
&or (p=s; $p; p++)
0dd8oDnd($p?/0/);
)
void 0dd(:int 1 a, :int 1 9)
'
int carry, tep;
int erra, err9, na, n9;

carry=0;
Flear();
erra=a(JetBast(na);
err9=9(JetBast(n9);
while (Gerra QQ Gerr9)
'
i& (erra)
tep=n9+carry;
else i& (err9)
tep=na+carry;
else
tep=na+n9+carry;
Pg: 49 de 69.
0dd8oIront(tepR10);
carry=tep%10;
erra=a(JetLrevio#s(na);
err9=9(JetLrevio#s(n9);
)
i& (carry 6 0)
0dd8oIront(carry);
)
void Lrint()
'
int n, err;

err=JetIirst(n);
while( Gerr )
'
co#t ** n;
err=JetCe!t(n);
)
co#t ** endl;
)
);
) seguinte fun%&o main testa a classe Sint somando dois n'meros e imprimindo o
resultado da soma6
void ain()
'
:int a("1,-.32P");
:int 9("1,-.");
:int c;
c(0dd(a,9);
c(Lrint();
)
Os construtores e a fun%&o Print s&o simples e facilmente compreens(veis.
) fun%&o Add talvez remeta voc aos dias de banco escolar porue faz adi%&o " moda
antiga. Come%a com os dois 'ltimos d(gitos de cada um dos n'meros a serem somadosT
soma esses dois d(gitosT salva o resultado e anota o valor da casa da dezena decorrente
da soma 87"ai um7?. Dove-se ent&o para o elemento anterior da lista e repete as mesmas
opera%*es. 0rovavelmente os dois n'meros mint n&o ten#am a mesma uantidade de
d(gitos! portanto o cCdigo deve certificar-se de ue n&o est operando alm do d(gito mais
a esuerda de um dos n'meros mint. Isso feito usando as variveis erra e errb.
Buando os dois n'meros mint forem inteiramente processados! o cCdigo verifica a
e$istncia de "ai um e salva o 'ltimo d(gito! se necessrio.
+$ecutando o cCdigo de teste voc ver ue a classe Sint funciona como descrito aui e
pode somar dois n'meros de at =EE d(gitos cada um.
)pCs usar a classe Sint algumas vezes! voc come%ar a perceber um problema com a
fun%&o Add - n&o # como escrever algo parecido com m D m + 4 j ue o formato
Pg: 50 de 69.
obrigatCrio da c#amada de Add m.AddEm,oneF! onde a varivel one foi inicializada com
conte'do 4. ) causa dessa limita%&o ue Add deve limpar a rea destinada a conter a
soma antes de salvar a( ualuer resultado. Isso leva a perda de dados uando a fun%&o
Add usada para m.AddEm,oneF.
) solu%&o para esse problema nos leva a cria%&o de uma rea temporria para conter o
resultado durante a e$ecu%&o da soma. )o trmino da fun%&o! o resultado final deve ent&o
ser copiado para a instIncia atual. O pointer this usado para solu%&o desse problema!
como mostrado a seguir6
void 0dd(:int 1 a, :int 1 9)
'
int carry, tep;
int erra, err9, na, n9;
:int !;
carry=0;
erra=a(JetBast(na);
err9=9(JetBast(n9);
while (Gerra QQ Gerr9)
'
i& (erra)
tep=n9+carry;
else i& (err9)
tep=na+carry;
else
tep=na+n9+carry;
!(0dd8oIront(tepR10);
carry=tep%10;
erra=a(JetLrevio#s(na);
err9=9(JetLrevio#s(n9);
)
i& (carry 6 0)
!(0dd8oIront(carry);
$this = !;
)
Hessa 'ltima vers&o da fun%&o Add! foi criado uma varivel temporria denominada ;. O
resultado da soma colocado em ;! d(gito a d(gito. ) 'ltima lin#a do cCdigo da fun%&o
copia o conte'do de ; para a instIncia atual. O pointer this aponta para a instIncia
corrente da classe e pode ser aplicado a ualuer instIncia de classes em C++. +m
outras palavras! this um pointer ue aponta para o conjunto dos dados membro 8a
estrutura de dados? ue formam a instIncia corrente da classe. Hesse caso nCs usamos
this para economia de cCdigo. Uma alternativa seria substituir a 'ltima lin#a da fun%&o
Add por
array = !(array;
co#nt = !(co#nt;
pointer = !(pointer;
$ !alor de Uthis a estrutura apontada por this. _ uma <orma mais e;pressa de se
copiar toda a estrutura de dados de uma s- 'e=.
Pg: 51 de 69.
Como e$emplo final da classe Sint! vamos us-la para implementar um localizador de
n'mero 1ibonacci. ) seUncia 1ibonacci tem a seguinte forma6
1, 1, ,, -, 3, S, 1-, ,1, -., etc(
Cada n'mero na seuncia a soma dos dois n'meros anteriores.
0ara implementar a fun%&o ue ueremos vamos precisar de um modo de verificar
igualdade em n'meros mint de modo a poder controlar um loop. ) fun%&o membro
seguinte poderia ser acrescentada a classe Sint para verificar igualdade entre dois
n'meros mint6
int DH#al(:int 1 a)
'
i& (a(@i"e()G=@i"e())
ret#rn 0;
else
'
int i, na, n9;
a(JetIirst(na);
JetIirst(n9);
&or (i=0; i * a(@i"e(); i++)
i& (naG=n9)
ret#rn 0;
else
'
a(JetCe!t(na);
JetCe!t(n9);
)
ret#rn 1;
)
)
Implementada essa nova fun%&o! o seguinte cCdigo vai encontrar o centsimo n'mero em
uma seuncia 1ibonacci6
void ain()
'
:int a!("100");
:int co#nter("1"), one("1");
:int t1("0"), t,("1");
:int d;
do
'
d(0dd(t1,t,);
t1=t,;
t,=d;
co#nter(0dd(co#nter,one);
) while (Gco#nter(DH#al(a!));
d(Lrint();
)
Pg: 52 de 69.
O cCdigo usa duas variveis t4 e t5 para conter os valores anteriores. +sses valores s&o
somados e t4 e t5 s&o atualizados para os prC$imos dois valores. O contador
incrementado e o loop continua at ue o contador atinja o valor pr-determinado. Usando
esse cCdigo! o centsimo n'mero foi encontrado6
-3.(,,.(S.S(1P4(,21(413(0P3
7." M Conclus+o
Heste tutorial voc viu como o mecanismo de #eran%a usado para criar uma #ieraruia
de classes! e como a e$istncia de #eran%a favorece o desenvolvimento de cCdigo com
uma abordagem no sentido do mais genrico para o mais espec(fico. ) classe Sint um
e$emplo perfeito dessa abordagem6 uma classe genrica foi usada para construir a
classe Sint porque um mint nada mais do que um lista de d3gitos)
+mbora ten#amos atingido nosso objetivo! a classe Sint ainda n&o est bem integrada
aos recursos da linguagem. HCs ainda vamos ver na prC$ima se%&o o uso do operador +
para a fun%&o de soma e do operador DD para a de igualdade.
&obrecarga de operador
Ho tutorial anterior nCs implementamos uma vers&o da classe Sint! e finalizamos com o
cCdigo ue calcula elementos da seuncia 1ibonacci. O cCdigo usado para e$ecutar o
clculo era
void ain()
'
:int a!("100");
:int co#nter("1"), one("1");
:int t1("0"), t,("1");
:int d;

do
'
d(0dd(t1,t,);
t1=t,;
t,=d;
co#nter(0dd(co#nter,one);
) while (Gco#nter(DH#al(a!));
d(Lrint();
)
O desejvel ue pudssemos escrever esse mesmo cCdigo de modo semel#ante a um
cCdigo normal. Como o seguinte6
void ain()
'
:int a!("100");
:int co#nter("1");
:int t1("0"), t,("1");
:int d;
Pg: 53 de 69.
do
'
d = t1 + t,;
t1=t,;
t,=d;
co#nter = co#nter + "1";
) while (G (co#nter==a!));
co#t ** d ** endl;
)
C++ permite esse tipo de opera%&o com novos tipos de dados usando um processo
denominado sobrecarga de operador. Os operadores normais! como +, DD e OO s&o
sobrecarregados e passam a manejar tambm os novos tipos de dados.
)lguns casos de sobrecarga de operador envolvem o uso de fun%*es <riend. Uma fun%&o
<riend como uma fun%&o C normal! mas tem a permiss&o de acessar membros pri'ate
da classe dentro da ual declarada. O fato de ser como uma fun%&o C significa ue ela
n&o tem acesso ao pointer this! e tambm ue pode ser c#amada sem ue se identifiue
a classe para a ual ela opera. 0or e$emplo! uma fun%&o membro normal! tal como a
fun%&o Insert da classe Zist! reuer um instancia%&o de Zist para ue possa ser
c#amada.
Bist lst;
(((
lst(Ansert(3);
Uma fun%&o <riend n&o reuer necessariamente a instancia%&o de uma classe porue ela
n&o tem acesso ao pointer t#is.
Buase todos os operadores em C++ podem ser sobrecarregados6
+ ? $ % R T 1 Q
K G , = * 6 *= 6=
++ ?? ** 66 == G= 11 QQ
+= ?= %= R= T= 1 = Q= $=
**= 66= [ ] ( ) ?6 ?6$ new delete
)lguns desses operadores s&o usados raramente! e mais raramente ainda s&o
sobrecarregados. Das sobrecarregando os operadores mais comuns! como + e DD voc
pode dar " suas classes interfaces mais simples e autoe$plicativas.
O cCdigo seguinte mostra a classe Sint reformulada para usar os operadores +! DD e OO
sobrecarregados! e ainda um trec#o de cCdigo para testar o uso desses trs operadores.
class :intE p#9lic Bist
'
p#9licE
:int()EBist() ')
:int(char $s)EBist()
'
char $p;
Pg: 54 de 69.
&or (p=s; $p; p++)
0dd8oDnd($p?/0/);
)

&riend :int operator+ (:int 1 a, :int 1 9)
'
int carry, tep;
int erra, err9, na, n9;
:int !;

carry=0;
erra=a(JetBast(na);
err9=9(JetBast(n9);
while (Gerra QQ Gerr9)
'
i& (erra)
tep=n9+carry;
else i& (err9)
tep=na+carry;
else
tep=na+n9+carry;
!(0dd8oIront(tepR10);
carry=tep%10;
erra=a(JetLrevio#s(na);
err9=9(JetLrevio#s(n9);
)
i& (carry6 0)
!(0dd8oIront(carry);
ret#rn !;
)

int operator==(:int 1 a)
'
i& (a(@i"e()G=@i"e())
ret#rn 0;
else
'
int i, na, n9;
a(JetIirst(na);
JetIirst(n9);
&or (i=0; i * a(@i"e(); i++)
i& (naG=n9)
ret#rn 0;
else
'
a(JetCe!t(na);
JetCe!t(n9);
)
ret#rn 1;
)
)

Pg: 55 de 69.
&riend ostrea1 operator ** (ostrea1 s, :int 1 )
'
int n, err;

err=(JetIirst(n);
while( Gerr )
'
s ** n;
err=(JetCe!t(n);
)
ret#rn s;
)
);

void ain()
'
%% add two n#9ers
:int a("1,-.32P");
:int 9("1,-.");
:int c;

c = a + 9;
co#t ** "it/s &ine " ** c ** "(((really" ** endl;
co#t ** a + "----" ** endl;

%% &ind the 100th Ii9onacci n#9er
:int co#nter;
:int t1, t,;
:int d;

t1 = "0";
t, = "1";
co#nter = "1";
do
'
d = t1 + t,;
t1 = t,;
t, = d;
co#nter = co#nter + "1";
) while (G (co#nter == "100") );
co#t ** d ** endl;
)
,amos come%ar e$aminando a fun%&o DD6
int operator== (:int 1 a)
0orue esta uma fun%&o membro da classe Sint! esse cabe%al#o da fun%&o indica ue
o operador deve retornar um inteiro! ue usa o ue est a esuerda de DD como this! e
ue usa o ue est a direita de DD como um a. 5entro do cCdigo para a fun%&o do
operador DD! uando nCs usamos diretamente uma outra fun%&o! como ^etPirst! nCs
estamos nos referindo ao valor a esuerda de DD. )o contrrio! uma c#amada de fun%&o
Pg: 56 de 69.
no formato a.^etPirst refere-se ao ue est " direita de DD6
:int 9, ;
(((
i& (9 == )
O restante do cCdigo idntico ao da fun%&o E)ual ue vimos no /utorial Z. O valor
inteiro de retorno usado como resultado da compara%&o. Uma vez implementada essa
fun%&o! nosso operador DD c#amado sempre ue o compilador encontra um operador
DD entre dois valores do tipo Sint.
O operador + sobrecarregado uma fun%&o <riend6
&riend :int operator+ (:int 1 a, :int 1 9)
+ssa fun%&o declarada como uma <riend porue nCs n&o ueremos ue ela use
automaticamente o lado esuerdo do sinal de soma! porue essa fun%&o limpa a varivel
destinada ao resultado da soma! como j vimos no /utorial Z. Uma vez definida como
uma fun%&o <riend! ela se comporta como uma fun%&o C normal! sem acesso ao pointer
t#is. +la apenas soma os dois n'meros mint ue l#e forem passados! e retorna o
resultado no formato de um n'mero mint.
Ha fun%&o main # vrios comandos com a seguinte forma6
c = "----"
ou
c = c + "1"
Como o compilador sabe o ue fazerA Como ele sabe converter um >4> para um mintA
Uma vez ue ten#amos um construtor ue aceita um tipo charU! o construtor
automaticamente invocado na tentativa de fazer a combina%&o de tipos para o operador +.
.e nCs criarmos outro construtor ue aceite um parImetro do tipo inteiro longo! ent&o
poderemos escrever comandos como
c = c + 1;
) convers&o do valor inteiro 4 ser automtica. O seguinte comando n&o vai funcionar6
c = ",,,," + "----";
porue o compilador n&o tem nada ue l#e diga ue + significa a adi%&o de mints,
portanto ele n&o pode fazer a convers&o de tipos - um dos lados de + de"e ser um mint
para alertar o compilador.
O operador [[ tambm est sobrecarregado. ) fun%&o para sobrecarreg-lo deve ser uma
<riend porue o parImetro a esuerda n&o do mesmo tipo da classe. ) fun%&o deve
aceitar uma referncia para um parImetro ostream e um parImetro do tipo da classe.
5eve ainda retornar uma referncia para ostream.
Com essa fun%&o implementada! ualuer opera%&o de sa(da em C++ vai funcionar
normalmente com n'meros mint.
O operador CC sobrecarregado de modo similar6
Pg: 57 de 69.
&riend istrea1 operator 66 (istrea1 s, :int1 )
'
9#&[100];
s 66 9#&;
= 9#&; %% calls the constr#ctor
ret#rn s;
)
Outros operadores! tais como ++! +D! `D! etc podem ser facilmente sobrecarregados
usando os e$emplos acima.
Nrabalhando com pointers
9.0 Introdu%&o
9.4 1un%*es default
9.5 Conclus&o
9.0 M Introdu*+o
Buando uma classe contm dados membro ue s&o pointers! # uma srie de cuidados
adicionais para assegurar ue essa classe realmente funcione como esperado. 0or
e$emplo! uando uma instIncia de uma classe destru(da! o construtor deve certificar-se
ue todos os blocos de memCria dentro da classe sejam liberados. Um outro cuidado
envolve o operador de atribui%&o6 o comportamento padr&o para o operador D - cCpia de
todos os dados membro - como vimos at agora! n&o funciona para dados membro
pointers.
0ara tornar mais percept(vel essa diferen%a! vamos construir uma classe &tacH com
matriz e com pointers. )ui est a vers&o com matriz e uma fun%&o main contendo o
cCdigo para teste. 8+sse cCdigo idntico ao visto no /utorial <?.
7incl#de *iostrea(h6

class @tack
'
int stk[100];
int top;
p#9licE
@tack()E top(0) ')
K@tack() ')
void Flear() 'top=0;)

void L#sh(int i) 'i& (top * 100) stk[top++]=i;)
int Lop()
'
i& (top 6 0) ret#rn stk[??top];
else ret#rn 0;
)
Pg: 58 de 69.
int @i"e() 'ret#rn top;)
);

void ain()
'
@tack stack1, stack,;

stack1(L#sh(10);
stack1(L#sh(,0);
stack1(L#sh(-0);
co#t ** stack1(Lop() ** endl;
stack,=stack1;
co#t ** stack1(@i"e() ** endl;
co#t ** stack,(@i"e() ** endl;
co#t ** stack,(Lop() ** endl;
co#t ** stack,(Lop() ** endl;
)
O cCdigo seguinte implementa a mesma classe &tacH usando pointers! mas contm uma
srie de problemas ue iremos e$aminar em seguida.
typede& str#ct node
'
int data;
node $ne!t;
) node;

class @tack
'
node $top;
p#9licE
@tack()E top(0) ')
K@tack() ' Flear(); )
void Flear()
'
node $p=top;
while (p)
'
top = top?6ne!t;
delete p;
p = top;
)
)
void L#sh(int i)
'
node $p = new node;
p?6data = i;
p?6ne!t = top;
top = p;
)
int Lop()
'
i& (top G= 0)
Pg: 59 de 69.
'
int d = top?6data;
node $p=top;
top = top?6ne!t;
delete p;
ret#rn d;
)
else ret#rn 0;
)
int @i"e()
'
int c=0;
node $p=top;
while (p)
'
c++;
p = p?6ne!t;
)
ret#rn c;
)
);
+ssa uma implementa%&o completa da classe. +la realiza os procedimentos de
libera%&o de memCria dentro de seu destrutor! e funciona da mesma maneira ue vers&o
anterior da classe &tacH. Contudo! essa implementa%&o n&o funciona conforme o
esperado apCs um comando de atribui%&o como
stack1 = stack,;
O diagrama seguinte demonstra o ue acontece. ) opera%&o de atribui%&o! nesse caso!
apenas copia os dados membro de stacH5 para stacH4! dei$ando o mesmo conjunto de
dados em memCria sendo apontado por dois pointers.
)pCs a atribui%&o! os pointers stacH4.pop e stacH5.pop apontam ambos para a mesma
cadeia de blocos de memCria. .e uma das pil#as for e$clu(da! ou se uma delas e$ecutar a
fun%&o Pop! a outra pil#a vai apontar para um endere%o de memCria ue n&o mais ser
vlido.
+m algumas muinas esse cCdigo ser compilado sem erros e tudo parecer estar
correto por um certo tempo durante a e$ecu%&o do programa. Das t&o logo o sistema
comece a apontar para endere%os de memCria ue n&o mais sejam vlidos! a e$ecu%&o
Pg: 60 de 69.
come%ar a ter um comportamento errtico sem raz&o aparente at ue o programa
finalmente fal#e.
O ue precisamos de uma maneira de reformular a opera%&o de atribui%&o para criar
uma cCpia dos blocos de memCria apontados pelos pointers. Das de onde vem esse
operador de atribui%&o! e como podemos modific-loA
9.4 A Pun*Kes de<ault
Buando voc cria uma classe! uatro fun%*es default s&o criadas automaticamente e
ser&o utilizadas! a menos ue voc as sobrescreva. +ssas fun%*es default s&o6
O construtor default
O construtor de cCpia default
O operador de atribui%&o default
O destrutor default
O construtor default invocado uando voc declara uma instIncia da classe sem passar
ualuer parImetro. 0or e$emplo! se voc criar uma classe &ample sem a defini%&o
e$pl(cita de um construtor! ent&o o comando seguinte invoca o construtor default para s6
@aple s;
) seguinte declara%&o com inicializa%&o de s5 invoca o construtor de cCpia6
@aple s1;
@aple s, = s1;
O destrutor default c#amado uando se encerra o escopo dentro do ual a varivel foi
criada! e o construtor de atribui%&o c#amado uando ocorre uma opera%&o de atribui%&o
normal.
,oc pode sobrescrever ualuer um desses construtores! definindo as suas prCprias
fun%*es. 0or e$emplo! se voc define e$plicitamente um construtor para a classe! o
construtor default n&o ser criado pelo compilador.
O cCdigo seguinte vai nos ajudar a ter uma mel#or compreens&o do ue fazem o
construtor e o destrutor default6
7incl#de *iostrea(h6

class Flass0
'
int data0;
p#9licE
Flass0 () ' co#t ** "class0 constr#ctor" ** endl; )
KFlass0 () ' co#t ** "class0 destr#ctor" ** endl; )
);

class Flass1
Pg: 61 de 69.
'
int data1;
p#9licE
Flass1 () ' co#t ** "class1 constr#ctor" ** endl; )
KFlass1 () ' co#t ** "class1 destr#ctor" ** endl; )
);

class Flass,E p#9lic Flass1
'
int data,;
Flass0 c0;
);

void ain()
'
Flass, c;
)
) classe Class5 n&o tem construtor nem destrutor definidos e$plicitamente! mas esse
cCdigo produz a seguinte sa(da6
class= constructor
classE constructor
classE destructor
class= destructor
O ue aconteceu ue o compilador criou automaticamente tanto o construtor uanto o
destrutor default para Class5. O comportamento do default construtor c#amar o
construtor da classe base! bem como o construtor default para cada um dos dados
membro ue s&o classes. O destrutor default c#ama o destrutor da classe base e dos
dados membro ue s&o classes.
5igamos ue voc crie um novo construtor para Class5 ue aceite um inteiro. O
compilador ainda assim vai c#amar os necessrios construtores da classe base e dos
dados membro ue s&o classes.
O cCdigo seguinte demonstra esse processo6
class Flass,E p#9lic Flass1
'
int data,;
Flass0 c0;
p#9licE
Flass,(int i)
'
co#t ** "class, constr#ctor" ** endl;
)
Pg: 62 de 69.
);

void ain()
'
Flass, c(1);
)
Isso tambm funciona e produz a seguinte sa(da6
class= constructor
classE constructor
classQ constructor
classE destructor
class= destructor
Das agora voc n&o pode mais declarar uma varivel n&o inicializada do tipo Class5
porue n&o # mais um construtor default. O cCdigo seguinte demonstra6
Flass, c(1); %% <=
Flass, e; %% not <=??no de&a#lt constr#ctor
@ tambm poss(vel declarar uma matriz de uma classe! a menos ue n&o #aja um
construtor default definido.
Contudo! voc pode recriar o construtor default! criando e$plicitamente um construtor com
uma lista de parImetros vazia! da mesma maneira ue cria outros construtores para a
classe.
O operador de atribui%&o e o construtor de cCpia tambm s&o criados automaticamente.
)mbos apenas copiam os dados membro da instIncia " direita do sinal \ para a instIncia
" esuerda. Ho caso de nossa classe &tacH! nCs ueremos eliminar essas fun%*es
default e usar fun%*es prCprias! para ue a opera%&o de atribui%&o funcione corretamente.
) seguir est&o as duas novas fun%*es para a classe &tacH! e a fun%&o CopJ
compartil#ada por ambas6
void Fopy(const @tack1 s)
'
node $H=0;
node $p=s(top;

while (p)
'
i& (top==0)
'
top = new node;
H=top;
)
else
'
Pg: 63 de 69.
H?6ne!t = new node;
H = H?6ne!t;
)

H?6data = p?6data;
p = p?6ne!t;
H?6ne!t=0;
)
)
@tack1 operator= (const @tack1 s) %%assignent
'
i& (this == 1 s)
ret#rn $this;
Flear();
Fopy(s);
ret#rn $this;
)
@tack(const @tack1 s)E top(0) %% copy constr#ctor
'
Fopy(s);
)
) fun%&o de atribui%&o se inicia verificando o caso de autoatribui%&o! como em
s D sT
.e verifica tratar-se de autoatribui%&o! a fun%&o n&o faz nada! ou seja! n&o efetua a
autoatribui%&o. H&o sendo autoatribui%&o! a fun%&o limpa a instIncia recipiente e copia a
lista ligada e$istente na memCria! de modo ue a instIncia " esuerda do operador de
atribui%&o ten#a sua prCpria cCpia da pil#a.
O construtor de cCpia basicamente o mesmo ue ualuer outro construtor. @ usado
para manejar os seguintes casos6
@tack s1;
s1(L#sh(10);
s1(L#sh(,0);
@tack s,(s1); %% copy constr#ctor invoked
@tack s- = s1; %% copy constr#ctor invoked
Uma vez implementados o operador de atribui%&o e o construtor de cCpia! a classe &tacH
est completa. 0ode manejar ualuer condi%&o e funcionar corretamente.
9.5 M Conclus+o
/udo isso talvez l#e pare%a muito trabal#o a fazer! mas geralmente esses cuidados
adicionais s&o necessrios apenas uando se trabal#a com pointers. O ue acontece
ue voc tem ue realmente proteger suas estruturas baseadas em pointers contra
contingncias ue invalidem os dados.
+m alguns programa em C! os programadores poder&o fazer pressuposi%*es como eu
Pg: 64 de 69.
posso apontar o mesmo bloco de mem"ria com !rios pointers sem problemas,
porque nessa parte do c"digo nada modifica os blocos apontados. Contudo! se um
outro programador viola essa pressuposi%&o! ainda ue acidentalmente! o programa pode
fal#ar! e fal#as decorrentes de problemas com pointers s&o dif(ceis de seguir e de
localizar.
/ais problemas n&o v&o ocorrer em uma classe C++ definida com seguran%a! porue
todas essas contingncias est&o previamente consideradas e cobertas.
,oc pode verificar ue a implementa%&o mostrada acima ainda ineficiente. O ue
acontecer se voc uiser ter apenas uma cCpia dos blocos de memCria ue formam a
pil#aA 0or e$emplo! o ue acontecer se os dados da pil#a ocuparem alguns megab:tes
de memCria! e voc n&o tiver memCria suficiente para fazer uma cCpiaA
O ue voc faz nesse caso usar uma tcnica como um contador de re<er(ncias - cada
instIncia da classe incrementa uma varivel global esttica ue contm o n'mero de
instIncias usando a mesma cCpia dos dados. Cada destrutor decrementa esse mesmo
contador. .omente uando um construtor! apCs decrementar o contador! detecta ue n&o
# mais ualuer instIncia da classe usando os dados! ue realmente se libera a
memCria usada para conter os dados.
Pun*Kes 'irtuais
)o longo desses tutoriais nCs vimos vrios e$emplos de #eran%a! porue #eran%a muito
importante para programa%&o orientada a objeto. ,imos ue #eran%a permite ue dados
membro e ue fun%*es membro sejam acrescentadas "s fun%*es derivadas. ,imos
tambm vrios e$emplos em ue o mecanismo de #eran%a foi usado para modificar o
comportamento de uma fun%&o. 0or e$emplo! no /utorial > nCs vimos um e$emplo onde a
fun%&o Insert da classe base Zist foi sobreposta por uma outra fun%&o Insert ue
contin#a totaliza%&o.
Uma #ieraruia similar mostrada a seguir! usando uma classe base denominada Zist e
uma classe derivada denominada NotalingZist6
7incl#de *iostrea(h6

class Bist
'
int array[100];
int co#nt;
p#9licE
Bist()E co#nt(0) ')
void Ansert(int n) ' array[co#nt++]=n; )
int Jet(int i) ' ret#rn array[i]; )
int @i"e() ' ret#rn co#nt; )
);

void :anipBist(Bist list)
'
Pg: 65 de 69.
%% do things to the list
list(Ansert(100);
list(Ansert(,00);
%% do things to the list
)

class 8otalingBistE p#9lic Bist
'
int total;
p#9licE
8otalingBist()E Bist(), total(0) ')
void Ansert(int n)
'
total += n;
BistEEAnsert(n);
)
int Jet8otal() ' ret#rn total; )
);

void ain()
'
8otalingBist list;
int !;

list(Ansert(10);
list(Ansert(3);
co#t ** list(Jet8otal() ** endl;
:anipBist(list);
co#t ** list(Jet8otal() ** endl;
&or (!=0; ! * list(@i"e(); !++)
co#t ** list(Jet(!) ** / /;
co#t ** endl;
)
Hesse cCdigo! a classe Zist implementa a lista mais simples poss(vel com as trs fun%*es
membro Insert! ^et e &i=e e o construtor. ) fun%&o SanipZist um e$emplo de uma
fun%&o ualuer ue usa a classe Zist! e ue c#ama a fun%&o Insert duas vezes apenas
como ilustra%&o do ue pretendemos demonstrar.
) classe NotalingZist #erda a classe Zist e acrescenta um dado membro denominado
total. +sse dado membro armazena o total corrente de todos os n'meros contidos na
lista. ) fun%&o Insert sobreposta para ue total seja atualizado a cada inser%&o.
) fun%&o main declara uma instIncia da classe NotalingZist. Insere os valores 40 e 7 e
imprime o total. +m seguida c#ama SanipZist. 0ode ser uma surpresa para voc ue
essa constru%&o n&o resulte em erro de compila%&o6 se voc ol#ar o protCtipo de
Pg: 66 de 69.
SanipZist vai ver ue ela espera uma parImetro do tipo Zist! e n&o do tipo NotalingZist.
)contece ue C++ entende certas peculiaridades sobre #eran%a! uma delas ue um
parImetro do tipo classe base deve aceitar tambm ualuer tipo classe derivada dauela
classe base. 0ortanto! desde ue NotalingZist derivada da classe Zist! SanipZist vai
aceitar um parImetro do tipo NotalingZist. +sse um dos recursos do C++ ue torna o
mecanismo de #eran%a t&o poderoso6 voc pode criar classes derivadas e pass-las para
fun%*es e$istentes ue con#ecem apenas a classe base.
Buando o cCdigo mostrado for e$ecutado! ele n&o vai produzir o resultado correto. +le vai
produzir a seguinte sa(da6
=Z
=Z
=E Z
+ssa sa(da indica ue n&o apenas a totaliza%&o n&o funcionou! mas ue os valores 400 e
500 n&o foram inseridos na lista uando da c#amada a SanipZist. Uma parte desse erro
se deve a um erro no cCdigo6 o parImetro aceito por SanipZist deve ser um pointer ou
uma referncia! do contrrio nen#um valor ser retornado. Dodificando o protCtipo de
SanipZist para corrigir parcialmente o problema6
void :anipBist(Bist1 list)
)gora teremos a seguinte sa(da6
13
13
10 3 100 ,00
@ didtico seguir a e$ecu%&o de SanipZist passo-a-passo e observar o ue acontece.
Buando ocorre a c#amada para a fun%&o Insert! a fun%&o invocada Zist:Insert ao invs
de NotalingZist:Insert.
+sse problema tambm pode ser resolvido. @ poss(vel! em C++! criar uma fun%&o com um
prefi$o 'irtual! e isso le!a o 788 a sempre chamar a funo na classe deri!ada. Ou
seja! uando uma fun%&o declarada como 'irtual! o compilador pode c#amar vers*es
da fun%&o ue seuer e$istiam uando o cCdigo da fun%&o c#amada foi escrito. 0ara
verificar isso! acrescente a palavra 'irtual a frente das fun%*es Insert tanto na classe Zist
uanto na classe NotalingZist! como mostrado a seguir6
class Bist
'
int array[100];
int co#nt;
p#9licE
Bist()E co#nt(0) ')
virt#al void Ansert(int n) ' array[co#nt++]=n; )
int Jet(int i) ' ret#rn array[i]; )
int @i"e() ' ret#rn co#nt; )
);

Pg: 67 de 69.
void :anipBist(Bist1 list)

'
%% do things to the list
list(Ansert(100);
list(Ansert(,00);
%% do things to the list
)

class 8otalingBistE p#9lic Bist
'
int total;
p#9licE
8otalingBist()E Bist(), total(0) ')
virt#al void Ansert(int n)
'
total += n;
BistEEAnsert(n);
)
int Jet8otal() ' ret#rn total; )
);
;e fato necessrio colocar a pala!ra 'irtual apenas a frente do nome da funo na
classe base, mas um bom hbito repeti-la nas funes das classes deri!adas,
como uma indicao e#pl3cita do que est ocorrendo.
)gora voc pode e$ecutar o programa e obter as sa(das corretas6
13
-13
10 3 100 ,00
O ue est acontecendoA ) palavra 'irtual a frente da fun%&o determina para o C++ ue
voc planeja criar novas vers*es dessa mesma fun%&o em classes derivadas. Ou seja!
'irtual permite ue voc declare suas futuras inten%*es em rela%&o " classe em
defini%&o. Buando uma fun%&o 'irtual c#amada! o C++ e$amina a classe ue c#amou a
fun%&o! e busca a vers&o da fun%&o para esta classe! mesmo ue a classe derivada ainda
n&o e$istisse uando a c#amada da fun%&o foi escrita.
Isso significa ue em certos casos voc tem ue pensar no futuro uando escreve o
cCdigo. ,oc deve refletir eu, ou qualquer outro programador, poderia no futuro
precisar modificar o comportamento dessa funo' .e a resposta for sim ent&o a
fun%&o deve ser declarada como 'irtual.
5eve-se ter alguns cuidados para ue uma fun%&o 'irtual funcione corretamente. 0or
e$emplo! voc deve realmente prever a necessidade de se modificar o comportamento da
fun%&o e lembrar-se de declar-la como 'irtual na classe base. Um outro ponto
importante pode ser visto no e$emplo acima6 e$perimente remover o ] da lista de
parImetros em SanipZist e siga o cCdigo passo a passo. Desmo a fun%&o Insert
Pg: 68 de 69.
estando marcada como 'irtual na classe base! a fun%&o Zist::Insert c#amada! ao invs
da fun%&o NotalingZist::Insert.
Isso acontece porue! uando o X n&o est presente! a lista de tipos de parImetros em
Zist est atuando como se fosse uma defini%&o de convers&o de tipos. Bualuer classe
passada convertida para a classe base Zist. Buando o X est presente na lista de
parImetros! tal convers&o n&o acontece.
0ode-se ver fun%*es virtuais em praticamente toda #ieraruia de classes em C++. Um
#ieraruia de classes t(pica espera ue! no futuro! se altere o comportamento das fun%*es
para adaptar a biblioteca de classes "s necessidades espec(ficas de uma ou de outra
aplica%&o.
1un%*es virtuais s&o usadas com freuncia uando o projetista da classe n&o pode
realmente saber o ue ser feito com a classe no futuro. .upon#a ue voc est usando
a interface de uma classe ue implementa buttons na tela. Buando voc cria uma
instIncia do button! ele se desen#a na tela e se comporta de modo padr&o! ou seja!
ilumina-se uando clicado pelo usurio. +ntretanto! o programador ue projetou essa
classe n&o tin#a idia do ue os programadores usurios da classe poderiam uerer fazer
uando o button fosse clicado. 0ara esses casos! o projetista da classe poderia ter
definido uma fun%&o 'irtual denominada! por e$emplo! handleE'ent ue c#amada
sempre ue o button clicado. 1eito isso! voc pode sobrescrever a fun%&o virtual com
uma fun%&o prCpria ue maneja a situa%&o do modo mais adeuado " sua aplica%&o.
Conclus+o
Cobrimos uma grande uantidade de temas nessa srie de tutoriais! mas voc talvez
ten#a a sensa%&o de ue ainda # muito o ue se aprofundar em C++. Isso verdade em
certo sentido6 C++ uma linguagem muito profunda! com algumas sutilezas e artif(cios
ue somente a e$perincia pode l#e ajudar a dominar. C tambm assim! sC ue em
escala menor.
) 'nica maneira de se compreender completamente uma linguagem de programa%&o
escrever! e ler! muito cCdigo. ,oc pode aprender muito usando! e estudando! bibliotecas
criadas por outros. /odos os benef(cios do C++ se tornar&o mais evidentes para voc na
medida em ue voc compreenda mais e mais essa linguagem. +nt&o... vamos "
codifica%&oW
Pg: 69 de 69.

You might also like