Noteque
p
n~aoeumobjetodaclasset3DVector
,massimumponteiroparaumobjeto da classet3DVector
. O objeto propriamente dito,*p
, esta na area de memoria de alocac~aodin^amica,oheapdosistema. (Ooperadornew
e,sobalgunsaspectos, similara func~ao
malloc
,porem muito superior, como veremosposteriormente.)O conteudo de um objeto, ou seu estado interno, e denido por suas variaveis de inst^ancia,declaradasnadenic~aodeclasse. Osvetores
v
e*p
possuemestadosinternos (distintos) caracterizados pelas variaveisx
,y
ez
(linhas 30-32 do Programa 8.1), as quais representam suas coordenadas Cartesianas. Podemoster, tambem,variaveisque n~ao pertencem a qualquer inst^ancia de uma classe, mas que s~ao compartilhadas por todas as inst^ancias da classe. Em Smalltalk [47], essas variaveispertencem a classe, e n~aoasinst^anciasdaclasse e,porisso, s~aodenominadasvariaveisde classe. EmC++, umavariaveldeclasseedeclaradacomoespecicadordetipostatic
,comonaslinhas 34-36 do Programa8.1.8.2.3 Mensagem
Vamos supor que
s
seja uma estrutura talcomo denida no Programa3.1. Se quis es-semos acessarum dos camposdes
,porexemplo, a coordenadax
, escreveramoss.x
. A mesma regra sintatica vale em C++. Adicionalmente, podemos \acessar" tambem asfunc~oes denidas na classe:v.Normalize();
p->SetCoordinates(1,1,1);
Noexemplo acima, estamos\acessando" ometodo
Normalize
dovetorv
e o metodoSetCoordinates
do vetor apontado porp
. Semanticamente, porem, o signicado e outro. Oqueestamos fazendo,naverdade,eenviando umamensagem paraosobjetosv
e*p
,umasolicitac~aoparaqueessesobjetosexecutemalgumaoperac~ao. Oprograma 2anteriorquer dizer,emC++,\
v
,porfavor,normalize-se"e\*p
,porfavor,ajustesuas coordenadas para (1;1;1)." Quando enviamos uma mensagem a um objeto, dizemos aoobjetoo que fazer,e n~aocomo fazer.Uma mensagem e denida por um receptor, por um seletor e por um conjunto, eventualmente vazio, de par^ametros. Na segunda linha do exemplo acima,
*p
e o receptor da mensagem,SetCoordinates
e o seletor da mensagem e1,1,1
s~ao os par^ametros damensagem.Quando umobjetorecebeuma mensagem,ometodocorrespondenteamensageme executado. Em C++, o \metodo correspondente a uma mensagem"e a func~ao mem-bro, declarada na denic~ao da classe do objeto, que possui o mesmo nome do seletor da mensagem e o mesmo numero e tipo de par^ametros da mensagem. (Note que po-demos ter metodos com o mesmo nome, desde que com tipos e/ou numero distintos de par^ametros, como nas linhas 8-9 do Programa 8.1.) Chamamos essa operac~ao de acoplamento mensagem/metodo. Portanto, em resposta a mensagem
SetCoordina-tes(1,1,1)
, o vetor*p
\acopla" e executa o metodoSetCoordinates
declarado na linha 9 do programa. O valor retornado por um objeto, como resultado do pro-cessamento de uma mensagem, e o proprio valor da func~ao membro correspondente (eventualmente,void
).Em um programa orientado a objetos, a computac~ao e realizada por objetos que trocam mensagensentre si. Consideraremos somente omodelopassivode objetos,isto e, um objeto que envia uma mensagem para um outro objeto n~ao executa mais nada enquanto n~aoobtiver, da parte doreceptor, resposta da mensagem enviada.
8.2.4 Construc~ao e Destruic~ao de Objetos em C++
Imediatamenteaposaconstruc~aodeumobjeto,seuestadointernodeveserinicializado. EmC++, issoe feitopelaexecuc~ao de metodos especiais chamadosconstrutores. Um construtoremC++eumafunc~aosem tipoderetorno(nemmesmo
void
)cujonomee id^enticoaonomedaclasse. Aclasset3DVector
,comopodemosobservarnaslinhas4-6 doPrograma8.1, possuitr^esconstrutores. Oprimeiron~aotomaquaisquer par^ametros e e chamado de construtor default. O segundo toma como par^ametro uma refer^encia para um objeto constantedaclasset3DVector
;esse construtor echamadoconstrutor de copia ee utilizadoparainicializaroestado internodoobjetosendo construdo com uma copia do estado interno do objeto passado como par^ametro. O terceiro toma como par^ametros tr^es numeros reais correspondentes as coordenadas do vetor sendo construdo.No momento da declarac~ao de um objeto em C++, estatica ou dinamicamente como visto acima, podemos enviar uma mensagem ao novo objeto solicitando sua inicializac~ao. Porexemplo,
t3DVector u(2,2,2);
t3DVector w(u);
Estamosdizendo, acima,\
u
,porfavor,inicialize-secom ascoordenadas(2;2;2)"e\w
, por favor, inicialize-se com uma copia deu
." (Se n~ao enviarmos mensagem alguma naconstruc~ao de um novoobjeto, ocompilador automaticamentechama o construtor defaultda classe,sehouver. Se nenhum construtor default fordeclarado, ocompiladorC++e uma linguagem quen~ao possui \coleta de lixo" automatica. Por isso, todo objeto que utilizar memoria din^amica deve liberar a memoria utilizada antes de ser destrudo. Em C++, ha metodos especiais, chamados de destrutores, que podem ser denidos para executar essa tarefa. Um destrutor, se declarado em uma classe, e chamadoautomaticaeimediatamenteantes da destruic~aode um objeto daclasse. (Se n~ao ha destrutor, o compilador fornece um.) Um destrutor e denido em uma classe C++ por uma func~ao com o mesmo nome da classe precedido pelo smbolo
˜
, sem argumentos e sem tipo de retorno. A classet3DVector
n~ao possui destrutor (veja a proximaSec~ao).O tempo de vida de um objeto em um programa C++ e denido pelas regras de escopo da linguagem, tal como no C.
3
Um objeto criado dentro de um bloco sera destrudoaonaldobloco(amensagemeenviadaautomaticamentepelocompilador). A unica excec~ao e para aqueles objetos criados dinamicamente. Nesse caso, devemos explicitamente invocar o destrutor do objeto, utilizando o operador
delete
. Para o vetor*p
, escrevemosdelete p;
(Ooperador
delete
e, sob alguns aspectos, similar afunc~aofree
,porem, da mesma formaqueooperadornew
,muitosuperior. Umdosmotivosequedelete
n~aosomente libera memoria, mas envia uma mensagem ao objeto solicitando, e ao mesmo tempo permitindo, queeste facasua propria \limpeza".)8.3 Propriedades da Orientac~ao a Objetos
Por que precisamos de uma classe de objetos? Poderamos argumentar que a classe
t3DVector
, por exemplo, nos permite modularizar um pouco mais o codigo, porque estamos denindo, em uma unica unidade, as estruturas de dados e osprocedimentos que manipulam essas estruturas. Mas, se o benefcio fosse somente esse, poderamos consegu-lo com uma boa pratica de programac~ao em C. Antes de prosseguirmos a discuss~ao, vejamos dois conceitos relacionados aprogramac~aoorientada a objetos:Abstrac~ao. A abstrac~aoeum dosmecanismos maisimportantesutilizadospela mente humana para compreender o mundo real. Ao analisarmos um problema complexo,naturalmenteseparamosobjetosque,narealidade,nuncaseencontram isolados, caracterizando-os a partir de certas propriedades que denem aproxi-madamenteseus principaisaspectosestruturais ecomportamentais. Aabstrac~ao sempre deve ter algum proposito, porque e o proposito que permite determinar quais informac~oes ser~ao representadas e que operac~oes ser~ao executadas pelos objetos.
Tipos abstratos de dados. Tipo abstrato de dados e o mecanismo atraves do qualumalinguagemdeprogramac~aoorientadaaobjetosfornecesuportea especi-cac~aodas informac~oes de umobjetoedas operac~oes executadas porumobjeto, de forma similar ao tipo de dados de uma linguagem estruturada. A diferenca e que um tipo abstrato de dados esconde as informac~oes sobre a estrutura do 3
C++ n~aoadmitediretamenteoconceitodepersist^encia, epor isson~aoadiscutiremosaqui. Um objetopersistenteeumobjetoquesobreviveaexecuc~aodeumprograma,sendo,portanto,armazenado
objeto de observadores externos. Com isso, as abstrac~oes de um sistema s~ao de-nidas, napratica, porduas partes: uma interface que descreve quais operac~oes podem ser executadas e uma implementac~ao que determina como as operac~oes s~ao executadas. A classe e a construc~ao de linguagem mais comumente utiliza-dapara implementarum tipoabstrato de dados emlinguagens de programac~ao orientadas a objetos.
De acordo com a denic~ao de tipo abstrato de dados, as variaveisde inst^ancia decla-radas em uma denic~ao de classe deveriam ser \escondidas" de um observador exter-no, sendo acessveis somente aos proprios metodos da classe. Anal, as variaveis de inst^ancia denem o estado interno do objeto. Em C++, porem, somos livres para controlar a visibilidadede qualquer membro de uma classe, seja dado ou func~ao. Ob-serve, na linha 3 doPrograma 8.1, o uso da palavra reservada
public
. Signicaque, daquelepontoemdiante, todososmembrosdeclaradosnaclasses~aopublicos,podendo ser diretamenteacessados. Para um vetorv
, poderamos escrever, corretamente,v.x
paraobter (oualterar)ovalordacoordenada
x
dev
. Para osdefensores \puristas"da orientac~aoa objetos,essa possibilidadee inaceitavel e,mesmo em C++, e fortemente n~ao recomendavel. Vejamos por qu^e.8.3.1 Encapsulamento
Consideremos a denic~ao (parcial)da classe