Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Programas Simples para Testes de Funções Membro em C++, Notas de estudo de Sistemas de Informação

Neste documento, aprenda a criar e utilizar programas simples para testar funções membro em c++. O exemplo fornecido inclui a criação de uma estrutura chamada 'contador' e testes de seus métodos. Além disso, será apresentado um exemplo de classe 'vetor' e 'listaordenada'.

Tipologia: Notas de estudo

Antes de 2010

Compartilhado em 10/05/2009

ricardo-cesar-souza-oliveira-10
ricardo-cesar-souza-oliveira-10 🇧🇷

1 documento

1 / 178

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
NOTAS E RESTRIÇÕES DE USO DESTE DOCUMENTO:
ESTE DOCUMENTO É PROTEGIDO POR COPYRIGHT.
VOCÊ PODE USA-LO DESDE QUE COMO DE COSTUME FAÇA REFERÊNCIA A
ELE EM SEUS DOCUMENTOS.
USO RESTRITO, MODIFICAÇÕES E VENDA NÃO PERMITIDAS.
DICAS DE USO
ESTE DOCUMENTO ESTÁ PROTEGIDO, SÓ É PERMITIDA A LEITURA.
USE O MODO DE LEITURA LAYOUT DE PAGINA.
CASO VOCÊ TENHA PROBLEMAS DE FALTA DE MEMÓRIA NO SEU SISTEMA,
ELIMINE AS BARRAS DE FERRAMENTAS (TODAS).
CASO VOCÊ DESEJE FAZER COPY AND PASTE DOS PROGRAMAS É
RECOMENDÁVEL QUE USE A VERSÃO HIPERTEXTO POIS ESTA ESTÁ
PROTEGIDA.
PARA IMPRIMIR ESTE TEXTO, EM UMA IMPRESSORA QUE NAO SUPORTE
IMPRESSAO FRENTE E VERSO, SELECIONE A OPÇÃO IMPRIMIR PÁGINAS
ÍMPARES, DEPOIS VIRE AS PÁGINAS, REINSIRA NA IMPRESSORA E IMPRIMA
AS GINAS PARES, O TUTORIAL FICA MUITO MAIS COMPACTO, PORÉM
CUIDADO PARA NÃO DEIXAR O PAPEL ENROSCAR NA IMPRESSORA.
ENVIE SUGESTÕES, PROGRAMAS, CORREÇÕES, COLABORAÇÕES E DÚVIDAS
PARA: aacesta@dcc.unicamp.br
CASO VOCÊ ENCADERNAR A IMPRESSÃO, NÃO SE ESQUEÇA DE MOVER O
ÍNDICE ANALÍTICO DO FINAL PARA O COMEÇO DO DOCUMENTO.
CONTAMOS COM A SUA COLABORAÇÃO PARA MELHORIAS FUTURAS.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61
pf62
pf63
pf64

Pré-visualização parcial do texto

Baixe Programas Simples para Testes de Funções Membro em C++ e outras Notas de estudo em PDF para Sistemas de Informação, somente na Docsity!

NOTAS E RESTRIÇÕES DE USO DESTE DOCUMENTO:

• ESTE DOCUMENTO É PROTEGIDO POR COPYRIGHT.

• VOCÊ PODE USA-LO DESDE QUE COMO DE COSTUME FAÇA REFERÊNCIA A

ELE EM SEUS DOCUMENTOS.

• USO RESTRITO, MODIFICAÇÕES E VENDA NÃO PERMITIDAS.

DICAS DE USO

• ESTE DOCUMENTO ESTÁ PROTEGIDO, SÓ É PERMITIDA A LEITURA.

• USE O MODO DE LEITURA LAYOUT DE PAGINA.

• CASO VOCÊ TENHA PROBLEMAS DE FALTA DE MEMÓRIA NO SEU SISTEMA,

ELIMINE AS BARRAS DE FERRAMENTAS (TODAS).

• CASO VOCÊ DESEJE FAZER COPY AND PASTE DOS PROGRAMAS É

RECOMENDÁVEL QUE USE A VERSÃO HIPERTEXTO POIS ESTA ESTÁ

PROTEGIDA.

• PARA IMPRIMIR ESTE TEXTO, EM UMA IMPRESSORA QUE NAO SUPORTE

IMPRESSAO FRENTE E VERSO, SELECIONE A OPÇÃO IMPRIMIR PÁGINAS

ÍMPARES, DEPOIS VIRE AS PÁGINAS, REINSIRA NA IMPRESSORA E IMPRIMA

AS PÁGINAS PARES, O TUTORIAL FICA MUITO MAIS COMPACTO, PORÉM

CUIDADO PARA NÃO DEIXAR O PAPEL ENROSCAR NA IMPRESSORA.

• ENVIE SUGESTÕES, PROGRAMAS, CORREÇÕES, COLABORAÇÕES E DÚVIDAS

PARA: aacesta@dcc.unicamp.br

• CASO VOCÊ VÁ ENCADERNAR A IMPRESSÃO, NÃO SE ESQUEÇA DE MOVER O

ÍNDICE ANALÍTICO DO FINAL PARA O COMEÇO DO DOCUMENTO.

CONTAMOS COM A SUA COLABORAÇÃO PARA MELHORIAS FUTURAS.

TUTORIAL:

“C++ COMO UMA LINGUAGEM DE PROGRAMAÇÃO

ORIENTADA A OBJETOS.”

André Augusto Cesta. aacesta@dcc.unicamp.br

Orientadora: Prof

a

Dr

a

Cecília Mary Fischer Rubira

1.1 ESPECIFICANDO UMA CLASSE

Suponha um programa que controla um motor elétrico através de uma saída serial. A velocidade do motor é proporcional a tensão aplicada, e esta proporcional aos bits que vão para saída serial e passando por um conversor digital analógico. Vamos abstrair todos estes detalhes por enquanto e modelar somente a interface do motor como uma classe, a pergunta é que funções e que dados membro deve ter nossa classe, e que argumentos e valores de retorno devem ter essas funções membro: Representação da velocidade: A velocidade do motor será representada por um atributo, ou dado membro, inteiro (int). Usaremos a faixa de bits que precisarmos, caso o valor de bits necessário não possa ser fornecido pelo tipo , usaremos então o tipo long, isto depende do conversor digital analógico utilizado e do compilador. Representação da saída serial: O motor precisa conhecer a sua saída serial, a sua ligação com o “motor do mundo real”. Suponha uma representação em hexadecimal do atributo endereço de porta serial, um possível nome para o atributo: enderecomotor. Não se preocupe em saber como usar a representação hexadecimal. Alteração do valor da velocidade: Internamente o usuário da classe motor pode desejar alterar a velocidade, cria-se então o método ( em C++ função membro): void altera_velocidade(int novav);. O código anterior corresponde ao cabeçalho da função membro, ela é definida junto com a classe motor, associada a ela. O valor de retorno da função é void (valor vazio), poderia ser criado um valor de retorno (int) que indicasse se o valor de velocidade era permitido e foi alterado ou não era permitido e portanto não foi alterado. Não faz sentido usar, chamar, esta função membro separada de uma variável do tipo motor, mas então porque na lista de argumentos não se encontra um motor? Este pensamento reflete a maneira de associar dados e código (funções) das linguagens procedurais. Em linguagens orientadas a objetos o código e os dados são ligados de forma diferente, a própria declaração de um tipo definido pelo usuário já engloba as declarações das funções inerentes a este tipo, isto será explicado em 1.2.2. Note que não fornecemos o código da função, isto não é importante, por hora a preocupação é com a interface definida pela classe: suas funções membro e dados membro. Apenas pense que sua interface deve ser flexível de modo a não apresentar entraves para a criação do código que seria feita numa outra etapa. Nesta etapa teríamos que imaginar que o valor numérico da velocidade deve ir para o conversor onde irá se transformar numa diferença de potencial a ser aplicada nos terminais do motor, etc. Um diagrama simplificado da classe motor com os dados membro e as funções membro:

Exercícios: 1)Lembre-se de algum programa em que você trabalhou, cite que tipos de classes seriam criadas se esse programa fosse escrito em C++, que atributos e que funções membro estariam associadas a esses objetos? Exemplo: “Eu trabalhei em um programa de contas a pagar e contas a receber. Se esse programa fosse escrito em C++ eu definiria a classe conta_bancaria. Os atributos seriam: saldo, taxa_de_juros, limite_de_saque, etc. Minha opção seria por representá-los como variáveis do tipo float.” “Dentre as funções membros desta classe estariam funções para efetuar saques, depósitos e computar juros.” 1.2 STRUCT EM C++ Objetos são instâncias de uma classe. Quando um objeto é criado ele precisa ser inicializado, ou seja para uma única classe : Estudante de graduação podemos ter vários objetos num programa: Estudante de graduação Carlos, Identificação 941218, Curso Computação; Estudante de graduação Luiza , Identificação 943249, Curso Engenharia Civil... A classe representa somente o molde para a criação dos objetos, estes sim contém informação, veja tópico CLASSES E OBJETOS. 1.2.1 ATRIBUTOS OU DADOS MEMBRO. Este exemplo declara uma struct e em seguida cria um objeto deste tipo em main alterando o conteúdo desta variável. Uma struct é parecida com um record de Pascal, a nossa representa um círculo com os atributos raio, posição x , posição y, que são coordenadas cartesianas. Note que este objeto não possui funções membro ainda.

O acesso aos dados membro deve ser feito usando o nome do objeto e o nome do dado membro, separados por um ponto: ac.raio=10.0;. Note que raio sozinho não faz sentido no programa, precisa-se especificar de que objeto se deseja acessar o raio. Aos que programam em C: Os programadores C podem notar algo interessante: “C++ não requer a palavra struct na declaração da variável, ela se comporta como um tipo qualquer: int , float ...”. Outros programadores que não haviam usado struct previamente em C não se preocupem, façam apenas os exercícios deste exemplo e estarão aptos a prosseguir. Exercícios:

  1. Repita o mesmo exemplo só que agora mova o círculo alterando as componentes x e y. Ponha o círculo em (0.0,0.0) através de atribuições do tipo ac.x=1.0; mova o círculo para (1.0,1.0). Acompanhe todas as modificações da struct através de cout’s. 2)Simplifique o programa anterior retirando o atributo raio. Você pode dar o nome de ponto ou ponto_geometico para esta classe. 1.2.2 MÉTODOS OU FUNÇÕES MEMBRO. C++ permite que se acrescente funções de manipulação da struct em sua declaração, juntando tudo numa só entidade que é uma classe. Essas funções membro podem ter sua declaração (cabeçalho) e implementação (código) dentro da struct ou só o cabeçalho (assinatura) na struct e a implementação, código, fora. Este exemplo apresenta a primeira versão, o próximo a segunda versão (implementação fora da classe). Essas funções compõem a interface da classe. A terminologia usada para designá-las é bastante variada: funções membro, métodos, etc. Quando uma função membro é chamada, se diz que o objeto está recebendo uma mensagem (para executar uma ação). Um programa simples para testes sobre funções membro seria o seguinte: #include <iostream.h> struct contador //conta ocorrencias de algo { int num; //numero do contador void incrementa(void){num=num+1;}; //incrementa contador void comeca(void){num=0;}; //comeca a contar }; void main() //teste do contador {

contador umcontador; umcontador.comeca(); //nao esqueca dos parenteses, e uma funcao membro e nao atributo! cout << umcontador.num << endl; umcontador.incrementa(); cout << umcontador.num << endl; } Resultado do programa: 0 1 Comentários: O programa define um objeto que serve como contador, a implementação representa a contagem no atributo num que é um número inteiro. As funções membro são simples: incrementa adiciona um ao contador em qualquer estado e comeca inicializa a contagem em zero. Sintaxe: A sintaxe para declaração de funções membro dentro de uma classe é a mesma sintaxe de declaração de funções comuns :tipoderetorno nomedafuncao(lista_de_argumentos) { /*codigo */ }. A diferença é que como a função membro está definida na classe, ela ganho acesso direto aos dados membros, sem precisar usar o “ponto”, exemplo um_objeto.dadomembro;. Lembre-se que as chamadas de funções membro já se referem a um objeto específico, embora elas sejam definidas de uma forma geral para toda a classe. A sintaxe de chamada ou acesso à funções membro é semelhante a sintaxe de acesso aos dados membro com exceção dos parênteses que contém a lista de argumentos da função, mesmo que a lista seja vazia eles devem estar presentes: umcontador.incrementa();. Primeiro insere-se o nome do objeto e depois a chamada da função, estes são separados por um ponto. Cuidado para não esquecer os parênteses nas chamadas de funções membro em programas futuros, este é um erro bastante comum. Agora o programa mais complicado, porém baseado no exemplo 1.2.1: #include <iostream.h> //para cout struct circulo { float raio; float x; //atributo coordenada cartesiana x float y; //atributo coordenada cartesiana y void move(float dx,float dy) //função membro ou função membro move { x+=dx;

Como funcionam no compilador as chamadas de funções membro: É possível imaginar que as definições de funções membro ocupam um grande espaço na representação interna dos objetos, mas lembre-se que elas são todas iguais para uma classe então basta manter para cada classe uma tabela de funções membro que é consultada no momento da chamada. Os objetos só precisam ter uma referência para esta tabela. Exercícios: 1)Neste mesmo programa, crie uma função para a struct chamada “inicializa” que deve ter como argumentos um valor para x, um para y e outro para o raio, e deve alterar os atributos inicializando-os com os valores passados. Você pode abstrair o uso dessa função como uma maneira de inicializar o objeto de uma só vez embora a função o faça seqüencialmente. Comente as vantagens de fazê-lo, comparando com as outras opções, tenha sempre em mente a questão de segurança quando avaliar técnicas diferentes de programação. 2)No programa anterior, verifique que nada impede que você acesse diretamente os valores de x , y e raio e os modifique. Como você pode criar um número enorme de funções : altera_x(float a); move_raio(float dr); seria desejável que somente essas funções pudessem modificar x, y e raio. Você verá que isso é possível em encapsulamento 1.3. Por hora, crie essas funções. 3)Teste a função membro move com argumentos negativos, exemplo ac.move(-1.0,-1.5);. O resultado é coerente? 4)Crie uma nova struct que representa um ponto, que informações você precisa armazenar? Que funções seriam úteis? Faça um programa para testar sua classe. 5)Melhore a classe contador, defina uma função que imprime o contador na tela. Se você estivesse fazendo um programa para rodar numa interface gráfica com o usuário esta função de imprimir na tela seria a mesma? Definir uma função que retorna uma copia do valor atual do contador garante maior portabilidade? Por quê? Para aprender a retornar valores consulte: 1.2.3. 6)”Há uma tendência em definir o maior número de funções membro em uma classe, porque nunca se pode prever exatamente o seu uso em programas futuros”. Comente esta frase, tendo em vista o conceito de portabilidade. Você já é capaz de citar outras medidas que tornem suas classes mais portáveis? Leia o exercício anterior. 1.2.3 FUNÇÕES MEMBRO QUE RETORNAM VALORES. Até agora só tínhamos visto funções membro com valor de retorno igual a void. Uma função membro, assim como uma função comum, pode retornar qualquer tipo, inclusive os definidos pelo usuário. Sendo assim, sua chamada no programa se aplica a qualquer lugar onde se espera um tipo igual ou equivalente ao tipo do seu valor de retorno, seja numa lista de argumentos de outra função , numa atribuição ou num operador como o cout << variavel; #include <iostream.h>

struct contador //conta ocorrencias de algo { int num; //numero, posicao do contador void incrementa(void){num=num+1;}; //incrementa contador void comeca(void){num=0;}; //comeca a contar, "reset" int retorna_num(void) {return num;}; }; void main() //teste do contador { contador umcontador; umcontador.comeca(); //nao esqueca dos parenteses, e uma funcao membro nao dado! cout << umcontador.retorna_num() << endl; umcontador.incrementa(); cout << umcontador.retorna_num() << endl; } Resultado do programa: 0 1 1.2.4 FUNÇÕES DECLARADAS EXTERNAS A CLASSE , FUNÇÕES MEMBRO CHAMAMANDO FUNÇÕES MEMBRO. Este exemplo apresenta a implementação, definição, das funções fora da declaração da struct. Além disso introduz uma nova função chamada “inicializa” e funções float retorna_raio (void); e void altera_raio(float a). Inicializa coloca o ponto nas coordenadas passadas como seus argumentos. Introduzimos esta função membro aqui para preparar a explicação sobre construtores dada no próximo exemplo: 1.2.6. Comentários: Em uma declaração de uma classe normalmente se coloca a declaração das funções membro depois da declaração dos atributos, porém podemos fazer intercalações ou adotar qualquer ordem que nos convenha. O programador não é obrigado a implementar as funções membro dentro da declaração da classe, basta defini-las e apresentar a implementação em separado segundo a sintaxe (compilável) descrita a seguir: #include <iostream.h> struct teste

void circulo::altera_raio(float a) { raio=a; } float circulo::retorna_raio(void) { return raio; } void circulo::move(float dx,float dy) { x+=dx; y+=dy; } void circulo::mostra(void) { cout << "Raio:"<< retorna_raio() <<endl; cout << "X:"<<x << endl; cout << "Y:" <<y<< endl; } void main() { circulo ac; ac.inicializa(0.0,0.0,10.0); ac.mostra(); ac.move(1.0,1.0); ac.mostra(); ac.x=100.0; ac.altera_raio(12.0); ac.mostra(); } Comentários: Observe que a função membro mostra chama a função membro float retorna_raio(void) que é da mesma classe. Fica implícito da definição de mostra que retorna_raio() se aplica ao mesmo objeto instanciado que recebeu a chamada de mostra, ou seja, não é necessário usar o. na chamada de retorna_raio(). Em programas maiores, chamadas aninhadas de funções membro são bastante comuns. Programação orientada a objetos e interfaces gráficas com o usuário: Existem “libraries” de classes que permitem o programador C++ desenvolver aplicações para ambientes como o Microsoft Windows® de uma maneira bastante abstrata, este é um

exemplo claro de reuso de código, afinal o programador não precisa saber de detalhes da interface para programar nela. Resultado do programa: Raio: X: Y: Raio: X: Y: Raio: X: Y: Exercícios: 1)Implemente outras funções do estilo void altera_raio(float a) e float retorna_raio(void) para os atributos X e Y. 2)Faça um programa simples para testar uma struct que representa um mouse e que contém a posição na tela, os indicadores de estado dos botões e os função membros: clica_botaoA(void); move(float dx, float dy);. Não é preciso fazer a ligação da struct com a entrada serial, embora o leitor interessado possa encontrar na literatura de C exemplos de como fazê-lo, esta é uma tarefa complicada. Seu mouse deve ser capaz de caminhar para qualquer lugar da tela através de chamadas de funções membro, não deve ultrapassar os limites estabelecidos, e deve indicar se os botões estão pressionados ou não através de uma função semelhante a função mostra( ) deste exemplo. O mouse pode ter de 1 a 3 botões. E você pode substituir a função membro move(float dx,float dy) por move_x(float dx); e move_y(float dy); 1.2.5 ALGO PARECIDO EM UMA LINGUAGEM PROCEDURAL Este tópico apresenta uma comparação entre C++ e Pascal, para tal implementou-se dois programas semelhantes. O programa C++ é o programa círculo do tópico anterior: 1.2.4. O programa em Pascal vem a seguir: PROGRAM Comparacao; {COMPARACAO COM UM PROGRAMA C++} TYPE Circulo=RECORD x:real; {COORDENADAS X E Y} y:real; r:real; {somente dados} END;

Resultado do programa: X: 0.0000000000E+00 Y: 0.0000000000E+00 R: 1.0000000000E+ X: 1.0000000000E+00 Y: 1.0000000000E+00 R: 1.0000000000E+ X: 1.0000000000E+02 Y: 1.0000000000E+00 R: 1.2000000000E+ Comentários: C++: As classes em C++ englobam os dados membros e as funções membros. Para executar uma ação sobre o objeto ou relativa a este basta chamar uma função membro para este: ac.mostra(); A função membro não precisa de muitos argumentos, porque é própria da classe e portanto ganha acesso aos dados membro do objeto para ao qual ela foi associada: float circulo::retorna_raio(void) { return raio ; //tenho acesso direto a raio. } Pascal: Em Pascal os procedimentos e os dados são criados de forma separada, mesmo que só tenham sentido juntos. A junção entre os dados e procedimentos se dá através de passagem de parâmetros. No caso de uma linguagem procedural como Pascal, o que normalmente é feito se assemelha ao código seguinte: Move(ac,1.0,1.0);. Ac nesse caso é um “record”, mas sem funções membro, algo semelhante ao struct de C (não C++). Move, acessa os dados do “record” alterando os campos. O parâmetro é passado por referência e o procedimento é definido a parte do registro, embora só sirva para aceitar argumentos do tipo Circulo e mover suas coordenadas. Segurança: Em ambos programas (Pascal, C++) o programador pode acessar diretamente os dados do tipo definido pelo usuário: ac.x : =100.0; (Pascal) ou ac.x=100.0; (C++). Veremos em 1.3 ENCAPSULAMENTO maneiras de proibir em C++ este tipo de acesso direto ao dado membro, deixando este ser modificado somente pelas funções membro. Isto nos garante maior segurança e liberdade pois podemos permitir ou não o acesso para cada dado membro de acordo com nossa vontade. Eficiência: Alguém pode argumentar que programas que usam bastante chamadas de funções podem se tornar pouco eficientes e que poderia ser melhor acessar diretamente os dados de um tipo definido pelo usuário ao envés de passar por todo o trabalho de cópia de argumentos, inserção da função no pilha, etc. Em verdade não se perde muito em eficiência, e além disso muitas vezes não se deseja permitir sempre o acesso direto aos dados de um tipo definido pelo usuário por razões de segurança. Nesse sentido C++ oferece um recurso que permite ganhos em segurança sem perder muito em eficiência, veja: 1.5.2. Exercícios: 1)Verifique que em main() você pode modificar o atributo x do objeto da classe ponto ou círculo da seguinte forma: a.x=12.2;. Isto pode não ser muito útil, imagine-se criando uma library que implementa a classe ponto e uma série de funções relacionadas, por razões de segurança você gostaria que o usuário se limitasse ao uso da interface (funções membro) do objeto, como fazê-lo

será explicado em 1.3 encapsulamento. Por hora, apenas crie funções que ajudem a evitar este tipo de acesso direto. 1.2.6 CONSTRUTORES Construtores são funções membro especiais chamadas pelo sistema no momento da criação de um objeto. Elas não possuem valor de retorno, porque você não pode chamar um construtor para um objeto. Contrutores representam uma oportunidade de inicializar de forma organizada os objetos, imagine se você esquece de inicializar corretamente ou o faz duas vezes, etc. Um construtor tem sempre o mesmo nome da classe e não pode ser chamado pelo usuário desta. Para uma classe string o construtor teria a forma string(char* a); com o argumento char* especificado pelo programador. Ele seria chamado automaticamente no momento da criação, declaração de uma string: string a(“Texto”); //alocacao estatica implica na chamada do construtor a.mostra(); //chamada de metodos estatica. Existem variações sobre o tema que veremos mais tarde: Sobrecarga de construtor, “copy constructor”, como conseguir construtores virtuais (avançado, não apresentado neste texto) , construtor de corpo vazio. O exemplo a seguir é simples, semelhante aos anteriores, preste atenção na função membro com o mesmo nome que a classe (struct), este é o construtor: #include <iostream.h> struct ponto { float x; float y; public: ponto(float a,float b); //esse e o contrutor, note a ausencia do valor de retorno void mostra(void); void move(float dx,float dy); }; ponto::ponto(float a,float b) //construtor tem sempre o nome da classe. { x=a; //incializando atributos da classe y=b;

É lógico que neste exemplo this não tem muita utilidade, mas existem casos onde um objeto precisa passar seu ponteiro para alguma função que o modifica, ou fica possuindo uma referência para ele, então usa-se this. Veremos outras aplicações mais adiante.

  1. Introduza mensagens no construtor tipo: cout << “Objeto instanciado.”; introduza também trechos no seu programa parecidos com: cin >> a; , só para que o programa não rode todo de uma vez, rapidamente. O objetivo é acompanhar visualmente a seqüência de criação e modificação dos objetos. 3)Crie uma classe reta que tem como atributos dois objetos da classe ponto. Dica: Não use construtores , use funções do tipo inicializa(), já apresentadas. Quando seu programa ficar pronto acrescente função membros para esta reta tais como inclinação, coeficiente linear, etc. Para acrescentar construtores leia 1.2.7. Existem maneiras mais eficientes e compactas de representar uma reta, porém faça como foi sugerido, neste caso o objetivo não é eficiência. 1.2.7 CONSTRUTORES E AGREGAÇÃO O programa exemplo deste tópico cria uma classe reta com dois dados membro da classe ponto este exemplo é o resultado do exercício anterior, com um recurso a mais de C++. C++ permite que no construtor da classe reta, você chame os construtores dos atributos da classe ponto, se você não o fizer o compilador acusará um erro, pois os atributos ponto possuem construtores e eles precisam ser chamados para que a inicialização se complete de modo correto para o conjunto. Observe o código do construtor da classe reta usado no exemplo: reta(float x1,float y1,float x2,float y2):p1(x1,y1),p2(x2,y2) { //nada mais a fazer, os construtores de p1 e p2 ja foram chamados } p1(x1,y1) e p2(x2,y2) são as chamadas dos construtores da classe ponto, elas devem ficar fora do corpo {} do construtor, nesta lista separada por vírgulas você deve inicializar todos os atributos. Os tipos básicos como int, float, etc podem ser inicializados nessa lista. Por exemplo se a classe reta tivesse um atributo inteiro de nome identificação, a lista poderia ser da seguinte forma: reta(float x1,float y1,float x2,float y2):p1(x1,y1),p2(x2,y2),identificacao(10) { //nada mais a fazer, os construtores de p1 e p2 ja foram chamados } seria como se identificação tivesse um construtor que tem como argumento seu valor. ou reta(float x1,float y1,float x2,float y2):p1(x1,y1),p2(x2,y2)

identificacao=10; //tambem pode, porque tipos básicos (int) em C++ não são objetos // portanto nao tem construtores } Uma outra alternativa seria usar alocação dinâmica para os atributos pontos que passariam a ser agora ponteiros para pontos, deixaremos para discutir este tópico mais tarde em 1.5.3, mas saiba que nesse caso o construtor da classe reta não precisaria criar os pontos. Vamos ao exemplo, que novamente é semelhante aos anteriores, para que o leitor preste atenção somente nas mudanças, que são os conceitos novos, sem ter que se esforçar muito para entender o programa: #include <iostream.h> struct ponto { float x; float y; //coordenadas ponto(float a,float b) { x=a; y=b; } //construtor void move(float dx,float dy) { x+=dx; y+=dy; } //funcao membro comum void inicializa(float a,float b) { x=a; y=b; } void mostra(void) {cout << "X:" << x << " , Y:" << y << endl;} }; struct reta { ponto p1; ponto p2; reta(float x1,float y1,float x2,float y2):p1(x1,y1),p2(x2,y2) { //nada mais a fazer, os contrutores de p1 e p2 ja foram chamados