Tutorial c++ [Unicamp]

  • Upload
    uspcio

  • View
    239

  • Download
    0

Embed Size (px)

Citation preview

  • 8/8/2019 Tutorial c++ [Unicamp]

    1/188

    TUTORIAL:

    "C++ COMO UMA LINGUAGEM DE PROGRAMAOORIENTADA A OBJETOS."

    Copyright 1996

    Andr Augusto [email protected]

    Orientadora: Profa Dra Ceclia Mary Fischer Rubira

    PROGRAMAO ORIENTADA A OBJETOS

    Este tutorial se prope a ensinar programao orientada a objetos em C++. A maioria dos livros no apresenta alinguagem nesse contexto, dando uma ateno maior para os recursos de C++ do que para a metodologia de

    programao. recomendvel que o leitor tenha acesso a um desses livros visto que no ensinaremos aqui aspectos

    considerados bsicos que so em geral quase todos que permitem usar C++ como um C melhorado. Voc pode usarC++, como uma linguagem procedural com recursos avanados, mais uma vez no isso que pretendemos ensinarneste texto.

    Na prtica de programao orientada a objetos estaremos atentos em nossos programas para pontos como:

    -Compatibilidade, portabilidade.

    -Segurana.

    -Reusabilidade.

    -Facilidade de integrao.

    -Facilidade de extenso.

    -Eficincia.

    Os tpicos seguintes nos guiaro nesses objetivos, mostrando numa curva de aprendizado suave, como programarusando orientao a objetos em C++.

    1. CLASSES E OBJETOS

    Uma classe um tipo definido pelo usurio que contm o molde, a especificao para os objetos, assim como o tipointeiro contm o molde para as variveis declaradas como inteiros. A classe envolve, associa, funes e dados,controlando o acesso a estes, defin-la implica em especificar os seus atributos (dados) e suas funes membro(cdigo).

    Um programa que utiliza uma interface controladora de um motor eltrico provavelmente definiria a classe motor.Os atributos desta classe seriam: temperatura, velocidade, tenso aplicada. Estes provavelmente seriamrepresentados na classe por tipos como float ou long . As funes membro desta classe seriam funes paraalterar a velocidade, ler a temperatura, etc.

    Um programa editor de textos definiria a classe pargrafo que teria como um de seus atributos uma string ou umvetor de strings, e como funes membro, funes que operam sobre estas strings. Quando um novo pargrafo

    digitado no texto, o editor cria a partir da classe pargrafo um objeto contendo as informaes particulares do novotexto. Isto se chama instanciao ou criao do objeto.

    Classes podem ser declaradas usando a palavra reservada struct ou a palavra reservada class, nos exemplosposteriores entraremos em mais detalhes. As classes do prximo tpico 1.2 so declaradas com struct por razes

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    2/188

    didticas. Quando chegarmos em encapsulamento 1.3 mostraremos como declarar classes com class e no usaremosmais struct no tutorial.

    1.1. ESPECIFICANDO UMA CLASSE

    Suponha um programa que controla um motor eltrico atravs de uma sada serial. A velocidade do motor proporcional a tenso aplicada, e esta proporcional aos bits que vo para sada serial e passando por um conversordigital analgico.

    Vamos abstrair todos estes detalhes por enquanto e modelar somente a interface do motor como uma classe, apergunta que funes e que dados membro deve ter nossa classe, e que argumentos e valores de retorno devem teressas funes membro:

    Representao da velocidade:

    A velocidade do motor ser representada por um atributo, ou dado membro, inteiro (int). Usaremos a faixa de bitsque precisarmos, caso o valor de bits necessrio no possa ser fornecido pelo tipo , usaremos ento o tipo long , istodepende do conversor digital analgico utilizado e do compilador.

    Representao da sada serial:

    O motor precisa conhecer a sua sada serial, a sua ligao com o "motor do mundo real". Suponha umarepresentao em hexadecimal do atributo endereo de porta serial, um possvel nome para o atributo:enderecomotor. No se preocupe em saber como usar a representao hexadecimal.

    Alterao do valor da velocidade:

    Internamente o usurio da classe motor pode desejar alterar a velocidade, cria-se ento o mtodo ( em C++ funomembro): void altera_velocidade(int novav); . O cdigo anterior corresponde ao cabealho da funomembro, ela definida junto com a classe motor, associada a ela. O valor de retorno da funo void (valor vazio),

    poderia ser criado um valor de retorno (int) que indicasse se o valor de velocidade era permitido e foi alterado ouno era permitido e portanto no foi alterado.

    No faz sentido usar, chamar, esta funo membro separada de uma varivel do tipo motor, mas ento porque nalista de argumentos no se encontra um motor? Este pensamento reflete a maneira de associar dados e cdigo(funes) das linguagens procedurais. Em linguagens orientadas a objetos o cdigo e os dados so ligados de formadiferente, a prpria declarao de um tipo definido pelo usurio j engloba as declaraes das funes inerentes aeste tipo, isto ser explicado em 1.2.2.

    Note que no fornecemos o cdigo da funo, isto no importante, por hora a preocupao com a interfacedefinida pela classe: suas funes membro e dados membro. Apenas pense que sua interface deve ser flexvel demodo a no apresentar entraves para a criao do cdigo que seria feita numa outra etapa. Nesta etapa teramos queimaginar que o valor numrico da velocidade deve ir para o conversor onde ir se transformar numa diferena de

    potencial a ser aplicada nos terminais do motor, etc.

    Um diagrama simplificado da classe motor com os dados membro e as funes membro:

    Exerccios:

    1)Lembre-se de algum programa em que voc trabalhou, cite que tipos de classes seriam criadas se esse programafosse escrito em C++, que atributos e que funes 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 emC++ eu definiria a classe conta_bancaria. Os atributos seriam: saldo, taxa_de_juros, limite_de_saque, etc.

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    3/188

    Minha opo seria por represent-los como variveis do tipo float. "

    "Dentre as funes membros desta classe estariam funes para efetuar saques, depsitos e computar juros."

    1.2. STRUCT EM C++

    Objetos so instncias de uma classe. Quando um objeto criado ele precisa ser inicializado, ou seja para uma nicaclasse : Estudante de graduao podemos ter vrios objetos num programa: Estudante de graduao Carlos,

    Identificao 941218, Curso Computao; Estudante de graduao Luiza , Identificao 943249, Curso EngenhariaCivil... A classe representa somente o molde para a criao dos objetos, estes sim contm informao, veja tpicoclasses 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 contedo destavarivel. Uma struct parecida com um record de Pascal, a nossa representa um crculo com os atributos raio,

    posio x , posio y, que so coordenadas cartesianas. Note que este objeto no possui funes membro ainda.

    #include

    struct circulo

    //struct que representa um circulo.

    {

    float raio;

    float x;

    //posicoes em coordenadas cartesianas

    float y;

    };

    void main()

    {

    circulo ac;

    //criacao de variavel , veja comentarios.

    ac.raio=10.0;

    //modificacao de conteudo (atributos) da struct

    ac.x=1.0;

    //colocando o circulo em uma posicao determinada

    ac.y=1.0;

    //colocando o circulo em uma posicao determinada

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    4/188

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    5/188

    a primeira verso, o prximo a segunda verso (implementao fora da classe).

    Essas funes compem a interface da classe. A terminologia usada para design-las bastante variada: funesmembro, mtodos, etc. Quando uma funo membro chamada, se diz que o objeto est recebendo uma mensagem(para executar uma ao).

    Um programa simples para testes sobre funes membro seria o seguinte:

    #include

    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

  • 8/8/2019 Tutorial c++ [Unicamp]

    6/188

    Sintaxe:

    A sintaxe para declarao de funes membro dentro de uma classe a mesma sintaxe de declarao de funescomuns : tipoderetorno nomedafuncao(lista_de_argumentos) { /*codigo */ }. A diferena que como afuno 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 funes membro j se referem a um objetoespecfico, embora elas sejam definidas de uma forma geral para toda a classe.

    A sintaxe de chamada ou acesso funes membro semelhante a sintaxe de acesso aos dados membro comexceo dos parnteses que contm a lista de argumentos da funo, mesmo que a lista seja vazia eles devem estar

    presentes: umcontador.incrementa();.Primeiro insere-se o nome do objeto e depois a chamada da funo, estesso separados por um ponto. Cuidado para no esquecer os parnteses nas chamadas de funes membro em

    programas futuros, este um erro bastante comum.

    Agora o programa mais complicado, porm baseado no exemplo 1.2.1:

    #include //para cout

    struct circulo

    {

    float raio;

    float x;

    //atributo coordenada cartesiana x

    float y;

    //atributo coordenada cartesiana y

    void move(float dx,float dy)//funo membro ou funo membro move

    {

    x+=dx;

    //equivale a x=x+dx;

    y+=dy;

    }

    void mostra(void) //funo membro ou funo membro mostra

    {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    7/188

    circulo ac;

    // * instanciao de um objeto circulo (criacao)

    ac.x=0.0;

    ac.y=0.0;

    ac.raio=10.0;

    ac.mostra();

    ac.move(1.0,1.0);

    ac.mostra();

    ac.x=100.0;

    ac.mostra();

    }

    Resultado do programa:

    Raio:10

    X:0

    Y:0

    Raio:10

    X:1

    Y:1

    Raio:10

    X:100

    Y:1

    Comentrios:

    A funo membro move altera as coordenadas do objeto. O objeto tem suas coordenadas x e y somadas com os

    argumentos dessa funo membro. Note que esta funo membro representa uma maneira mais segura, clara,elegante de alterar as coordenadas do objeto do que acess-las diretamente da seguinte forma: ac.x+=dx;.ac.y+=dy;. Lembre-se que ac.x+=dx uma abreviao para ac.x=ac.x+dx; .

    Como funcionam no compilador as chamadas de funes membro:

    possvel imaginar que as definies de funes membro ocupam um grande espao na representao interna dosobjetos, mas lembre-se que elas so todas iguais para uma classe ento basta manter para cada classe uma tabela defunes membro que consultada no momento da chamada . Os objetos s precisam ter uma referncia para estatabela.

    Exerccios:

    1)Neste mesmo programa, crie uma funo para a struct chamada "inicializa" que deve ter como argumentos umvalor 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 funo como uma maneira de inicializar o objeto de uma s vez embora a funo ofaa seqencialmente. Comente as vantagens de faz-lo, comparando com as outras opes, tenha sempre em mente

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    8/188

    a questo de segurana quando avaliar tcnicas diferentes de programao.

    2)No programa anterior, verifique que nada impede que voc acesse diretamente os valores de x , y e raio e osmodifique. Como voc pode criar um nmero enorme de funes : altera_x(float a); move_raio(float dr);seria desejvel que somente essas funes pudessem modificar x, y e raio. Voc ver que isso possvel emencapsulamento 1.3. Por hora, crie essas funes.

    3)Teste a funo 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 informaes voc precisa armazenar? Que funes seriamteis ? Faa um programa para testar sua classe.

    5)Melhore a classe contador, defina uma funo que imprime o contador na tela. Se voc estivesse fazendo umprograma para rodar numa interface grfica com o usurio esta funo de imprimir na tela seria a mesma? Definiruma funo que retorna uma copia do valor atual do contador garante maior portabilidade? Por qu? Para aprender aretornar valores consulte: 1.2.3.

    6)"H uma tendncia em definir o maior nmero de funes membro em uma classe, porque nunca se pode preverexatamente 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 portveis? Leia o exerccio anterior.

    1.2.3. FUNES MEMBRO QUE RETORNAM VALORES.

    At agora s tnhamos visto funes membro com valor de retorno igual a void. Uma funo membro, assim comouma funo comum, pode retornar qualquer tipo, inclusive os definidos pelo usurio. 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, sejanuma lista de argumentos de outra funo , numa atribuio ou num operador como o cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    9/188

    //nao esqueca dos parenteses, e uma funcao membro nao dado!

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    10/188

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    11/188

    return raio;

    }

    void circulo::move(float dx,float dy)

    {

    x+=dx;

    y+=dy;

    }

    void circulo::mostra(void)

    {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    12/188

    Raio:10

    X:0

    Y:0

    Raio:10

    X:1

    Y:1

    Raio:12.0

    X:100.0

    Y:1

    Exerccios:

    1)Implemente outras funes do estilo void altera_raio(float a) e float retorna_raio(void) para os atributos X e Y.

    2)Faa um programa simples para testar uma struct que representa um mouse e que contm a posio na tela, osindicadores de estado dos botes e os funo membros: clica_botaoA(void); move(float dx, float dy);.

    No preciso fazer a ligao da struct com a entrada serial, embora o leitor interessado possa encontrar naliteratura de C exemplos de como faz-lo, esta uma tarefa complicada.

    Seu mouse deve ser capaz de caminhar para qualquer lugar da tela atravs de chamadas de funes membro, nodeve ultrapassar os limites estabelecidos, e deve indicar se os botes esto pressionados ou no atravs de umafuno semelhante a funo mostra( ) deste exemplo. O mouse pode ter de 1 a 3 botes. E voc pode substituir afuno 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 tpico apresenta uma comparao entre C++ e Pascal, para tal implementou-se dois programas semelhantes. Oprograma C++ o programa crculo do tpico 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;

    var ac:circulo;

    leitura:integer;

    PROCEDURE Inicializa(var altereme:Circulo;ax,by,cr:real);

    {COLOCA O CIRCULO EM DETERMINADA POSICAO}

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    13/188

    BEGIN

    altereme.x:=ax;

    altereme.y:=by;

    altereme.r:=cr;

    END;

    PROCEDURE Altera_Raio(var altereme:Circulo;ar:real);

    {ALTERA O RAIO DO CIRCULO}

    BEGIN

    altereme.r:=ar;

    END;

    FUNCTION Retorna_Raio(copieme:Circulo):real;

    BEGIN

    Retorna_Raio:=copieme.r;

    END;

    PROCEDURE Move(var altereme:Circulo;dx,dy:real);

    {MODE AS COORDENADAS X E Y ACRESCENTANDO DX E DY}

    BEGIN

    altereme.x:=altereme.x+dx;

    altereme.y:=altereme.y+dy;

    END;

    PROCEDURE Mostra(copieme:Circulo);

    {MOSTRA O CIRCULO NA TELA}

    BEGIN

    writeln('X:',copieme.x,' Y:',copieme.y,' R:',copieme.r);

    END;

    BEGIN

    {TESTES}

    Inicializa(ac,0.0,0.0,10.0);

    Mostra(ac);

    Move(ac,1.0,1.0);

    Mostra(ac);

    ac.x:=100.0;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    14/188

    Altera_Raio(ac,12.0);

    Mostra(ac);

    read(leitura);

    END.

    Resultado do programa:

    X: 0.0000000000E+00 Y: 0.0000000000E+00 R: 1.0000000000E+01

    X: 1.0000000000E+00 Y: 1.0000000000E+00 R: 1.0000000000E+01

    X: 1.0000000000E+02 Y: 1.0000000000E+00 R: 1.2000000000E+01

    Comentrios:

    C++:

    As classes em C++ englobam os dados membros e as funes membros. Para executar uma ao sobre o objeto ourelativa a este basta chamar uma funo membro para este: ac.mostra();

    A funo membro no precisa de muitos argumentos, porque prpria da classe e portanto ganha acesso aos dadosmembro 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 so criados de forma separada, mesmo que s tenham sentido juntos.

    A juno entre os dados e procedimentos se d atravs de passagem de parmetros. No caso de uma linguagemprocedural como Pascal, o que normalmente feito se assemelha ao cdigo seguinte: Move(ac,1.0,1.0); . Acnesse caso um "record", mas sem funes membro, algo semelhante ao struct de C (no C++). Move, acessaos dados do "record" alterando os campos. O parmetro passado por referncia e o procedimento definido a

    parte do registro, embora s sirva para aceitar argumentos do tipo Circulo e mover suas coordenadas.

    Segurana:

    Em ambos programas (Pascal, C++) o programador pode acessar diretamente os dados do tipo definido pelo usurio:ac.x:=100.0; (Pascal) ou ac.x=100.0; (C++).

    Veremos em 1.3ENCAPSULAMENTO maneiras de proibir em C++ este tipo de acesso direto ao dado membro,deixando este ser modificado somente pelas funes membro. Isto nos garante maior segurana e liberdade poispodemos permitir ou no o acesso para cada dado membro de acordo com nossa vontade.

    Eficincia:

    Algum pode argumentar que programas que usam bastante chamadas de funes podem se tornar pouco eficientese que poderia ser melhor acessar diretamente os dados de um tipo definido pelo usurio ao envs de passar por todoo trabalho de cpia de argumentos, insero da funo no pilha, etc.

    Em verdade no se perde muito em eficincia, e alm disso muitas vezes no se deseja permitir sempre o acessodireto aos dados de um tipo definido pelo usurio por razes de segurana. Nesse sentido C++ oferece um recurso

    que permite ganhos em segurana sem perder muito em eficincia, veja: 1.5.2.Exerccios:

    1)Verifique que em main() voc pode modificar o atributo x do objeto da classe ponto ou crculo da seguinte forma:a.x=12.2; . Isto pode no ser muito til, imagine-se criando uma library que implementa a classe ponto e uma srie

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    15/188

    de funes relacionadas, por razes de segurana voc gostaria que o usurio se limitasse ao uso da interface(funes membro) do objeto, como faz-lo ser explicado em 1.3 encapsulamento.Por hora, apenas crie funes queajudem a evitar este tipo de acesso direto.

    1.2.6. CONSTRUTORES

    Construtores so funes membro especiais chamadas pelo sistema no momento da criao de um objeto. Elas nopossuem valor de retorno, porque voc no pode chamar um construtor para um objeto. Contrutores representam

    uma oportunidade de inicializar de forma organizada os objetos, imagine se voc esquece de inicializar corretamenteou o faz duas vezes, etc.

    Um construtor tem sempre o mesmo nome da classe e no pode ser chamado pelo usurio desta. Para uma classestring o construtor teria a forma string(char* a); com o argumento char* especificado pelo programador. Eleseria chamado automaticamente no momento da criao, declarao de uma string:

    string a("Texto");

    //alocacao estatica implica na chamada do construtor

    a.mostra();

    //chamada de metodos estatica.

    Existem variaes sobre o tema que veremos mais tarde: Sobrecarga de construtor, "copy constructor", comoconseguir construtores virtuais (avanado, no apresentado neste texto) , construtor de corpo vazio.

    O exemplo a seguir simples, semelhante aos anteriores, preste ateno na funo membro com o mesmo nome quea classe (struct) , este o construtor:

    #include

    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;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    16/188

    //colocando a casa em ordem

    }

    void ponto::mostra(void)

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    17/188

    ponto(float a, float b)

    { this->inicializa(a,b); } //Verifique!

    lgico que neste exemplo this no tem muita utilidade, mas existem casos onde um objeto precisa passar seuponteiro para alguma funo que o modifica, ou fica possuindo uma referncia para ele, ento usa-se this. Veremosoutras aplicaes mais adiante.

    2) Introduza mensagens no construtor tipo: cout > a; , s para que o programa no rode todo de uma vez, rapidamente. O objetivo acompanhar visualmente a seqncia de criao e modificao dos objetos.

    3)Crie uma classe reta que tem como atributos dois objetos da classe ponto. Dica: No use construtores, usefunes do tipo inicializa(), j apresentadas. Quando seu programa ficar pronto acrescente funo membros

    para esta reta tais como inclinao, coeficiente linear, etc. Para acrescentar construtores leia 1.2.7 . Existem maneirasmais eficientes e compactas de representar uma reta, porm faa como foi sugerido, neste caso o objetivo no eficincia.

    1.2.7. CONSTRUTORES E AGREGAO

    O programa exemplo deste tpico cria uma classe reta com dois dados membro da classe ponto este exemplo oresultado do exerccio anterior, com um recurso a mais de C++. C++ permite que no construtor da classe reta, vocchame os construtores dos atributos da classe ponto, se voc no o fizer o compilador acusar um erro, pois osatributos ponto possuem construtores e eles precisam ser chamados para que a inicializao se complete de modocorreto para o conjunto. Observe o cdigo 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) so as chamadas dos construtores da classe ponto, elas devem ficar fora do corpo {} doconstrutor, nesta lista separada por vrgulas voc deve inicializar todos os atributos. Os tipos bsicos como int, float,etc podem ser inicializados nessa lista.

    Por exemplo se a classe reta tivesse um atributo inteiro de nome identificao, 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 identificao 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 bsicos (int) em C++ no so objetos

    // portanto nao tem construtores

    }

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    18/188

    Uma outra alternativa seria usar alocao dinmica para os atributos pontos que passariam a ser agora ponteiros parapontos, deixaremos para discutir este tpico mais tarde em 1.5.3, mas saiba que nesse caso o construtor da classereta no precisaria criar os pontos.

    Vamos ao exemplo, que novamente semelhante aos anteriores, para que o leitor preste ateno somente nasmudanas, que so os conceitos novos, sem ter que se esforar muito para entender o programa:

    #include

    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

  • 8/8/2019 Tutorial c++ [Unicamp]

    19/188

    void mostra(void);

    };

    void reta::mostra(void)

    {

    p1.mostra();

    p2.mostra();

    }

    void main()

    {

    reta r1(1.0,1.0,10.0,10.0); //instanciacao da reta r1

    r1.mostra();

    }

    Resultado do programa:

    X:1 , Y:1

    X:10 , Y:10

    Exerccios:

    1) Implemente um programa que use a mesma lgica do exemplo anterior para criar uma classe composta de outras .

    Voc estar usando agregao. Por exemplo um tringulo precisa de trs pontos para ser definido.

    2)Uma implementao mais eficiente da classe reta seria feita armazenando apenas um coeficiente angular e umlinear, mas esta reta deveria ento prover um construtor que aceitasse dois pontos como argumentos. Como vocno aprendeu sobrecarga de construtores (definir vrios construtores), use s um construtor que tem coeficienteangular e linear como argumentos e implemente esta nova classe reta sem usar agregao agora.

    3)Defina uma funo membro para a classe reta que retorna o ponto de intercesso com outra reta: pontoreta::intercessao(reta a);. No se esquea de tratar os casos degenerados, tais como retas paralelas ecoincidentes, use por exemplo mensagens de erro. Verifique que uma funo membro de uma reta recebe outra reta(mesmo tipo) como argumento. Dentro da funo membro os dados membro do argumento a devem ser acessadosdo seguinte modo:

    a.p1.x;

    Mais tarde, em 4.5 tratamento de excees, veremos maneiras melhores de lidar com esses casos degenerados.

    4)Defina uma funo membro chamada move para a classe reta, lembre-se de mover os dois pontos juntos (ainclinao no deve mudar).

    6)Defina uma funo membro void gira(tipox angulo); para a classe reta. Esta funo membro recebe umngulo como argumento, voc pode optar por representar o ngulo em radianos (float) ou criar a classe ngulo(graus, minutos, segundos). Resolva tambm o problema da escolha do ponto em torno do qual a reta deve sergirada. Use funes matemticas (seno cosseno) da library .

    1.2.8. DESTRUTORES.

    Anlogos aos construtores, os destrutores tambm so funes membro chamadas pelo sistema, s que elas sochamadas quando o objeto sai de escopo ou em alocao dinmica, tem seu ponteiro desalocado, ambas (construtor

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    20/188

    e destrutor) no possuem valor de retorno.

    Voc no pode chamar o destrutor, o que voc faz fornecer ao compilador o cdigo a ser executado quando oobjeto destrudo, apagado. Ao contrrio dos construtores, os destrutores no tem argumentos.

    Os destrutores so muito teis para "limpar a casa" quando um objeto deixa de ser usado, no escopo de uma funoem que foi criado, ou mesmo num bloco de cdigo. Quando usados em conjunto com alocao dinmica elesfornecem uma maneira muito prtica e segura de organizar o uso do "heap". A importncia dos destrutores em C++ aumentada pela ausncia de "garbage collection" ou coleta automtica de lixo.

    A sintaxe do destrutor simples, ele tambm tem o mesmo nome da classe s que precedido por ~ , ele no possuivalor de retorno e seu argumento void sempre:

    ~nomedaclasse(void) { /* Codigo do destrutor */ }

    O exemplo a seguir simples, porque melhorias e extenses sobre o tema destrutores sero apresentadas ao longo dotexto:

    //destrutor de uma classe

    #include

    struct contador{

    int num;

    contador(int n) {num=n;}

    //construtor

    void incrementa(void) {num+=1;}

    //funcao membro comum, pode ser chamada pelo usuario

    ~contador(void)

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    21/188

    }

    minutos.incrementa();

    }

    Resultado do programa:

    1

    11

    Contador destruido, valor:11

    Contador destruido, valor:2

    Comentrios:

    No escopo de main criado o contador minutos com valor inicial==0.

    Minutos incrementado, agora minutos.num==1.

    O valor de num em minutos impresso na tela.

    Um novo bloco de cdigo criado.

    Segundos criado, instanciado como uma varivel deste bloco de cdigo, o valor inicial de segundos 10, parano confundir com o objeto j criado.

    Segundos incrementado atingindo o valor 11.

    O valor de segundos impresso na tela.

    Finalizamos o bloco de cdigo em que foi criado segundos, agora ele sai de escopo, apagado, mas antes o sistemachama automaticamente o destrutor.

    Voltando ao bloco de cdigo de main(), minutos novamente incrementado.

    Finalizamos main(), agora, todas as variveis declaradas em main()saem de escopo, mas antes o sistema chama osdestrutores daquelas que os possuem.

    1.3. ENCAPSULAMENTO COM "CLASS"

    Encapsulamento, "data hiding". Neste tpico vamos falar das maneiras de restringir o acesso as declaraes de uma

    classe, isto feito em C++ atravs do uso das palavras reservadas public, private e protected. Friendstambm restringe o acesso a uma classe e apresentado em 4.1.

    Consideraes sobre C++:CONSIDERAES C++:1.5, apresenta tambm um recurso de C++ para declarar objetosconstantes e proteger argumentos de chamadas de mtodos que possam modific-los, usando const 1.5.1.

    No mais apresentaremos exemplos de classes declaradas com struct. Tudo que foi feito at agora pode ser feitocom a palavra class ao envs de struct, incluindo pequenas modificaes. Mas porque usar s class nessetutorial? A diferena que os dados membro e funes membro de uma struct so acessveis por "default" fora dastruct enquanto que os atributos e mtodos de uma classe no so, acessveis fora dela (main) por "default".Voc nem deve ter se preocupado com isso porque usando struct da forma como usvamos, tudo ficava acessvel.

    Ento como controlar o acesso de atributos e mtodos em uma classe? Simples, atravs das palavras reservadasprivate, public e protected.

    Protected ser explicada em 2.1 pois est relacionada com herana, por hora vamos focalizar nossa ateno emprivate e public que qualificam os dados membro e funes membro de uma classe quanto ao tipo de acesso(onde eles so visveis) . Public, private e protected podem ser vistos como qualificadores, "specifiers".

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    22/188

    Para facilitar a explicao suponha a seguintes declaraes equivalentes de classes:

    1)

    class ponto {

    float x;//dados membrofloat y;

    public:

    //qualificadorvoid inicializa(float a, float b) {x=a; y=b;};//funcao membrovoid move(float dx, float dy) {x+=dx; y+=dy; };

    };

    a declarao 1 equivale totalmente :

    2)

    class ponto {

    private:

    float x;float y;

    public:

    //qualificadorvoid inicializa(float a, float b) {x=a;y=b;};void move(float dx, float dy) {x+=dx;y+=dy; };

    };

    que equivale totalmente :

    3)

    struct ponto {

    private:

    //se eu nao colocar private eu perco o encapsulamento em struct.float x;float y;

    public:

    //qualificadorvoid inicializa(float a, float b) {x=a;y=b;};void move(float dx, float dy) {x+=dx; y+=dy;};

    };

    Fica fcil entender essas declaraes se voc pensar no seguinte: esses qualificadores se aplicam aos mtodos eatributos que vem aps eles, se houver ento um outro qualificador, teremos agora um novo tipo de acesso para osmtodos declarados posteriormente.

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    23/188

    Mas ento porque as declaraes so equivalentes? porque o qualificadorprivate "default" para class, ou sejase voc no especificar nada , at que se insira um qualificador, tudo o que for declarado numa classe private. Jem struct, o que default o qualificador public.

    Agora vamos entender o que private e o que public:

    Vamos supor que voc instanciou (criou) um objeto do tipo ponto em seu programa:

    ponto meu; //instanciacao

    Segundo o uso de qualquer uma das definies da classe ponto dadas acima voc no pode escrever no seuprograma:

    meu.x=5.0; //erro !

    ,como fazamos nos exemplos de 1.2 , a no ser que x fosse declarado depois de public na definio da classe o queno ocorre aqui. Mas voc pode escrever x=5.0; na implementao (dentro) de um mtodo porque enquanto nofor feito uso de herana, porque uma funo membro tem acesso a tudo que de sua classe, veja o programaseguinte.

    Voc pode escrever: meu.move(5.0,5.0); ,porque sua declarao (move) est na parte public da classe. Aqui o

    leitor j percebe que podem existir funes membro private tambm, e estas s so acessveis dentro do cdigo daclasse (outras funes membro).

    Visibilidade das declaraes de uma classe, fora dela e de sua hierarquia. Veja que s a parte public visvel nestecaso:

    Visibilidade das declaraes de uma classe, dentro dela mesma:

    Exerccios:

    1) Qual das seguintes declaraes permite que se acesse em main somente os mtodos move e inicializa,encapsulando todos os outros elementos da classe? Obs.: A ordem das reas private e public pode estar invertida

    com relao aos exemplos anteriores.a)

    struct ponto {

    //se eu nao colocar private eu perco o encapsulamento em struct.

    float x;

    float y;

    public:

    //qualificador

    void inicializa(float a, float b) {x=a; y=b;};

    void move(float dx, float dy) ; {x+=dx; y+=dy; };

    };

    b)

    class ponto {

    public:

    //qualificador

    void inicializa(float a, float b) {x=a; y=b;};

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    24/188

    void move(float dx, float dy) ; {x+=dx; y+=dy; };

    private:

    float x;

    float y;

    };

    c)

    class ponto {

    public:

    //qualificador

    void inicializa(float a, float b) {x=a; y=b;};

    //funcao membro

    void move(float dx, float dy) ; {x+=dx; y+=dy; };

    float x;

    //dados membro

    float y;

    };

    1.3.1. ATRIBUTOS PRIVATE, FUNES MEMBRO PUBLIC

    Aplicando encapsulamento a classe ponto definida anteriormente.

    #include

    class ponto

    {

    private:

    //nao precisaria por private, em class e default

    float x;

    //sao ocultos por default

    float y;

    //sao ocultos por default

    public:

    //daqui em diante tudo e acessivel.

    void inicializa(float a,float b)

    { x=a; y=b; }

    //as funcoes de uma classe podem acessar os atributos private dela mesma.

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    25/188

    void mostra(void)

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    26/188

    {

    float x;

    //sao ocultos por default

    public:

    //daqui em diante tudo e acessivel.

    ponto(float a,float b);

    //construtor tambem pode ser inline ou nao

    void mostra(void);

    void move(float dx,float dy);

    float y;

    //* Y nao e' mais ocultado

    };

    ponto::ponto(float a,float b)

    {

    x=a;

    y=b;

    }

    void ponto::mostra(void)

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    27/188

    }

    Resultado do programa:

    X:0 , Y:0

    X:1 , Y:1

    X:1 , Y:100

    Comentrios:

    Observe que agora nada impede que voc acesse diretamente y: ap.y=100.0, porm ap.x=10.00 um erro.Observe em que parte (rea) da classe cada um desses dados membro foi declarado.

    Exerccios:

    1)Crie os mtodos float retorna_x(void), void altera_x(float a); que devem servir para retornar o valorarmazenado em x e para alterar o valor armazenado em x respectivamente. Crie tambm as respectivas funesretorna e altera para todos os outros atributos.

    1.3.3. COMPILANDO UM PROGRAMA COM VRIOS ARQUIVOS.

    Compilando um programa dividido em vrios arquivos. Normalmente os programas C++ so divididos em arquivospara melhor organizao e encapsulamento, porm nada impede que o programador faa seu programa em um sarquivo. O programa exemplo da classe ponto de 1.3.1 poderia ser dividido da seguinte forma:

    //Arquivo 1 ponto.h, definicao para a classe ponto.

    class ponto

    {

    public:

    //daqui em diante tudo e acessivel.

    void inicializa(float a,float b);

    void mostra(void);

    private:

    float x;

    //sao ocultos por default

    float y;

    //sao ocultos por default

    };

    //Arquivo 2 , ponto.cpp , implementacao para a classe ponto.

    #include

    #include "ponto.h"

    void ponto::inicializa(float a,float b)

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    28/188

    { x=a; y=b; }

    //as funcoes de uma classe podem acessar os atributos private dela mesma.

    void ponto::mostra(void)

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    29/188

    //Codigo

    #endif

    #ifndef MLISTH_H

    #define MLISTH_H

    //defina aqui seu header file.

    //perceba que "Nomearq.h" e escrito na diretiva como NOMEARQ_H

    #endif

    Essas diretivas servem para evitar que um header file seja includo mais de uma vez no mesmo projeto. O seu uso sed da seguinte forma:

    Diagrama sugesto para organizao de programas relativamente simples:

    Saber compilar programas divididos em vrios arquivos muito importante. Isto requer um certo esforo por partedo programador, porque os mtodos podem variar de plataforma para plataforma. Pergunte para um programadorexperiente de seu grupo.

    Se o seu compilador de linha de comando, provavelmente voc poder compilar programas divididos em vriosarquivos usando makefiles. J se seu compilador opera num ambiente grfico, esta tarefa pode envolver a criao deum projeto.

    1.4. TIPO ABSTRATO DE DADOS

    Tipo abstrato de dados, TAD, se preocupa em proporcionar uma abstrao sobre uma estrutura de dados em termos

    de uma interface bem definida. So importantes os aspectos de encapsulamento, que mantm a integridade do objetoevitando acessos inesperados, e o fato de o cdigo estar armazenado em um s lugar o que cria um programamodificvel, legvel, coeso.

    Uma classe implementa um tipo abstrato de dados.

    So exemplos de tipos abstratos de dados:

    1) Uma rvore binria com as operaes usuais de insero, remoo, busca ...

    2)Uma representao para nmeros racionais (numerador, denominador) que possua as operaes aritmticasbsicas e outras de converso de tipos.

    3)Uma representao para ngulos na forma (Graus, Minutos, Segundos). Tambm com as operaes relacionadas,bem como as operaes para converter para radianos, entre outras.

    Tipo abstrato de dados um conceito muito importante em programao orientada a objeto e por este motivo logoapresentado neste tutorial. Os exemplos seguintes so simples devido ao fato de no podermos usar todos os recursosC++ por razes didticas. Devido a esta importncia, a medida em que formos introduzindo novos recursosexemplificaremos tambm com aplicaes na implementao tipos abstratos de dados.

    1.4.1. TAD FRAO

    Tipo abstrato de dados frao. Baseado no conceito de nmero racional do campo da matemtica. Algumas

    operaes no foram implementadas por serem semelhantes s existentes. O exemplo mais completo se encontra em4.1.2. Por hora no podemos fazer uso de recursos avanados como sobrecarga de operador e templates.

    Resumo das operaes matemticas envolvidas:

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    30/188

    Simplificao de frao: (a/b)=( (a/mdc(a,b)) / (b/mdc(a,b)) )

    Onde mdc(a,b) retorna o mximo divisor comum de ab.

    Soma de frao: (a/b)+(c/d)=( (a.d+c.b) / b.d ) simplificada.

    Multiplicao de frao: (a/b) * (c/d)= ( (a*c) / (b*d) ) simplificada.

    Igualdade: (a/b)== (c/d) se a*d == b*c.

    No igualdade: (a/b) != (c/d) se a*d b*c

    Maior ou igual que: (a/b)(c/d) se a*d b*c

    Tpicos abordados:

    Construtores em geral, destrutores, tipo long, criando mtodos de converso de tipos, mtodos chamando mtodosdo mesmo objeto, operador % que retorna o resto da diviso de dois inteiros.

    //header file para o TAD fracao.

    //File easyfra.h

    long mdc(long n,long d);

    //maximo divisor comum metodo de Euclides.

    class fracao {

    private:

    long num;

    //numerador

    long den;

    //denominador

    public:

    fracao(long t,long m);

    //construtor comum

    void simplifica(void);//divisao pelo mdc

    ~fracao() { /* nao faz nada*/ }

    //Nao e preciso fazer nada.

    //operacoes matematicas basicas

    fracao soma (fracao j);

    fracao multiplicacao(fracao j);

    //operacoes de comparacao

    int igual(fracao t);

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    31/188

    int diferente(fracao t);

    int maiorouigual(fracao t);

    //operacoes de input output

    void mostra(void);

    //exibe fracao no video

    void cria(void);

    //pergunta ao usuario o valor da fracao

    //operacoes de conversao de tipos

    double convertedbl(void);

    //converte para double

    long convertelng(void);

    //converte para long

    };

    //implementacao para a classe fracao.

    #include

    #include "easyfra.h"

    long mdc(long n,long d)

    //maximo divisor comum

    //metodo de Euclides +- 300 anos AC.

    {

    if (n

  • 8/8/2019 Tutorial c++ [Unicamp]

    32/188

    long commd;

    commd=mdc(num,den);

    //divisor comum

    num=num/commd;

    den=den/commd;

    if (den

  • 8/8/2019 Tutorial c++ [Unicamp]

    33/188

    }

    int fracao::maiorouigual(fracao t)

    {

    return ((num*t.den)>=(t.num*den));

    }

    void fracao::mostra(void)

    {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    34/188

    //nossa definicao da classe

    #include

    main()

    {

    fracao a(0,1),b(0,1);

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    35/188

    }

    Comentrios:

    Observe o seguinte cdigo usado no programa: fracao c(a.soma(b));. O resultado de a.soma(b) uma frao,mas no criamos um construtor que recebe uma frao como argumento, como isso foi possvel no programa?

    Simples, a linguagem oferece para as classes que voc cria a cpia bit a bit. Cuidado com o uso dessa cpia em

    conjunto com alocao dinmica, objetos podero ter cpias iguais de ponteiros, ou seja compartilhar uso deposies na memria. De qualquer forma, em 0 explicaremos como redefinir esta cpia de modo a evitar situaesindesejveis como a cpia de ponteiros e em 1.5.3 explicaremos melhor os perigos de usar este tipo de cpia emconjunto com alocao dinmica.

    Resultado do programa:

    Entre com fracao a: Numerador:4

    Denominador:2

    (2/1) Entre com fracao b: Numerador:5

    Denominador:3

    (5/3)

    c de a+b:(11/3)

    a*b(10/3)

    a+b(11/3)

    a>=b1

    a==b0

    a!=b1

    long(a) 2

    double(a) 2

    Exerccios:

    1) Modifique o tipo frao para aceitar as seguintes funes membro.

    long retorna_num(void) {return num;}long altera_den(float a) { den=a;}

    Considerando que os atributos declarados em private no so acessveis fora da classe, descreva a utilidade dessasfunes. Eles so teis se usadas pelas prprias funes membro de frao?

    *2) Implemente o tipo abstrato de dados nmero complexo com as operaes matemticas inerentes. Faa antes umprojeto das funes membro que sero implementadas descrevendo tambm as operaes matemticas necessrias.

    *3) Outro tipo abstrato de dados extremamente til o tipo abstrato de dados string que deve fornecer: copyconstructor, operaes de comparao ( ordem lexicogrfica ), concatenao, substring , entre outras. Implemente

    este tipo abstrato de dados, tendo em mente a seguinte pergunta: "Voc poderia substituir um tipo fracao ou inteirousado em uma rotina de ordenacao pela sua implementao de string sem fazer grandes modificaes?". Essapergunta final ser muito importante quando comearmos a discutir templates 4.3.

    4)Continue trabalhando no TAD frao, implemente os mtodos restantes (menor que, subtrao) de modo anlogo

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    36/188

    s implementaes fornecidas.

    5)Pesquise sobre matrizes em C++. Crie um tipo abstrato de dados matriz que suporte atribuies e leituras declulas contendo elementos do tipo float. Crie outros mtodos para este tipo abstrato de dados como multiplicao

    por uma constante.

    1.5. CONSIDERAES C++:

    Neste tpico iremos explicar recursos mais particulares de C++, porm no menos importantes para a programaoorientada a objetos na linguagem. Alguns recursos como const que est relacionado com encapsulamento poderoser retirados deste tpico em novas verses do tutorial.

    1.5.1. CONST

    Este exemplo mostra o uso de funes const e sua importncia para o encapsulamento. Const pode qualificar umparmetro de funo (assegurando que este no ser modificado), uma funo membro (assegurando que esta nomodifica os dados membro de sua classe), ou uma instncia de objeto/tipo (assegurando que este no sermodificado.)

    Os modos de qualificao descritos atuam em conjunto, para assegurar que um objeto const no ser modificado,C++ s permite que sejam chamados para este objeto funes membro qualificadas como const. Const tambmum qualificador, "specifier".

    #include

    #include

    //double sqrt(double x); de math.h retorna raiz quadrada do numero

    //double pow(double x, double y); de math.h calcula x a potencia de y

    const float ZERO=0.0;

    class ponto

    {

    private:

    float x;

    //sao ocultos por default nao precisaria private mas e' bom

    float y;//sao ocultos por default

    public:

    //daqui em diante tudo e acessivel em main.

    ponto(float a,float b)

    { x=a; y=b; }

    void mostra(void) const

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    37/188

    {

    return

    float(

    sqrt(

    (

    pow(double(hi.x-x),2.0)

    +

    pow(double(hi.y-y),2.0)

    )

    )

    );

    //teorema de Pitagoras

    }

    };

    void main()

    {

    ponto ap(3.0,4.0);

    //instanciacao

    ap.mostra();

    //funcoes membro public

    const ponto origem(ZERO,ZERO);

    //defino objeto constante

    origem.mostra();

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    38/188

    const float ZERO=0.0;

    Const qualificando funes:

    float distancia(const ponto hi) const;

    Const qualificando argumentos:

    float distancia(const ponto hi) const;

    Exerccios:

    1)Use tudo o que voc aprendeu sobre const na classe reta, definida em CONSTRUTORES E AGREGAO 1.2.7.

    1.5.2. FUNES INLINE

    Requisitos:

    Saber como um programa se comporta na memria, em termos de chamadas de funo e gerenciamento da pilha,"stack".

    O que so funes inline: Imagine uma chamada de uma funo membro void altera_raio(float a) da classe circulo japresentada, ac.altera_raio(a). Esta chamada envolve a passagem de parmetros, insero da funo na pilha(stack), retorno de um valor(void), tudo isso representa uma diminuio da velocidade do programa com relaoa um simples: ac.raio=a; que nesse caso funcionaria muito bem.

    Ocorre que ns desejamos usar chamadas de mtodos, vimos inclusive meios de esconder, encapsular o atributo raiopara que a nica alternativa para alterar seu valor seja atravs da chamada de altera_raio(a). Porque programardesta forma? Porque mais seguro, mais prximo dos princpios de orientao a objetos. Em verdade POO secaracteriza por muitas chamadas de mtodos e uso do "heap", rea de memria usada pela alocao dinmica.

    O que as funes declaradas como inline fazem traduzir a chamada do mtodo em tempo de compilao em umequivalente ac.raio=17.0. evitando todo o contratempo descrito. Essa traduo do mtodo colocada na

    sequncia de cdigo do programa, voc pode ter vrios trechos que chamariam funes, desviariam o fluxo doprograma at o retorno desta, convertidos em instrues simples. Como desvantagem temos o aumento do tamanhodo programa, visto que passaro a existir vrias cpias diferentes da funo no programa (uma para cada argumento)ao envs de um s prottipo de funo que era colocado na pilha no momento da chamada e ento tinha osargumentos substitudos.

    Nos programa anteriores sobre a classe crculo, se a funo membro mostra fosse inline haveria uma converso dachamada interna (dentro de mostra) de retorna_raio()em simplesmente ac.raio. Pode haver converso devrias funes inline aninhadas, estas converses so seguras, porque so feitas pelo compilador.

    Normalmente vantajoso usar inline para funes pequenas que no aumentem muito o tamanho do programa oufunes onde velocidade crucial. Aqui vale a conhecida regra 80:20, oitenta porcento do tempo do programa

    gasto em vinte por cento dos mtodos. Porm o programador no precisa se preocupar muito com funes inlinena fase de desenvolvimento, este um recurso C++ para aumento de eficincia que pode muito bem ser deixado

    para o final do projeto. Saiba porm que as diferenas de tempo decorrentes de seu uso so sensveis.

    Este exemplo explora as possibilidades que temos para declarar funes membro e como declar-las para que sejamdo tipo inline:

    #include

    struct ponto

    {

    float x;

    float y;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    39/188

    void inicializa(float a,float b)

    { x=a; y=b; } //Apesar de nao especificado compilador tenta

    //expandir chamada da funcao como inline porque esta dentro da definicao da classe.

    void mostra(void); //com certeza nao e' inline, externa a classe e sem qualificador.

    inline void move(float dx,float dy); //e' inline , prototipo, definicao

    };

    void ponto::mostra(void)

    {cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    40/188

    X:100 , Y:1

    1.5.3. ALOCAO DINMICA COM NEW E DELETE.

    Neste tpico sero apresentados os recursos de C++ para alocao dinmica de variveis de tipos simples e objetos,ou seja, estudaremos a alocao de estruturas em tempo de execuo.

    1.5.3.1. PONTEIROS, "POINTERS"

    Este exemplo mostra como trabalhar com ponteiros para variveis de tipos pr-definidos (no definidos pelo usurio)usando new e delete.

    O programa a seguir cria um ponteiro para uma varivel inteira, aloca memria para esta varivel e imprime seuvalor.

    #include

    void main()

    {

    int* a;

    //declara um ponteiro para endereco de variavel inteira

    a=new int(3);

    //aloca memoria para o apontado por a, gravando neste o valor 3

    cout uma seta, ou flecha que voc pode ler como "oapontado" novamente. Os parnteses em (*a).dd so necessrios devido a precedncia do operador . com relaoao *. Esta sintaxe abreviada ser bastante usada quando alocarmos dinamicamente objetos.

    Observao:

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    41/188

    int* a;

    a=new int(3);

    pode ser abreviado por:

    int* a=new int(3);

    1.5.3.2. VETORES CRIADOS ESTATICAMENTE

    O exemplo a seguir aloca estaticamente, em tempo de compilao, um vetor de inteiros com trs posies. Emseguida, gravamos as trs posies e as mostramos na tela:

    #include

    void main()

    {

    int a[3];

    //aloca o vetor de tamanho 3, estaticamente

    a[0]=1;

    //atribui a posicao indice 0 do vetor

    a[1]=2;

    //atribui 2 a posicao indice 1 do vetor

    a[2]=3;

    //atribui 3 a posicao indice 2 do vetor

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    42/188

    embora desastroso escrever em nosso programa a[4]=3;. O compilador calcula o endereo de memria da posio4 com base na posio inicial do vetor e o tamanho do tipo alocado. Aps calculado o endereo da posio 4 o valor3 copiado, apagando o contedo anterior!

    Comentrios:

    Note que no estamos usando ponteiros neste exemplo e por isso que o vetor alocado estaticamente, em tempode compilao, tambm por este motivo que o argumento que vai no lugar do 3 no cdigo int a[3]; deve seruma expresso constante e no uma varivel.

    1.5.3.3. COPIA DE OBJETOS COM VETORES ALOCADOS ESTATICAMENTE.

    No primeiro exemplo do TAD frao vimos que o compilador fornece cpia bit a bit para objetos, alertamos tambmsobre o perigo de usar este tipo de cpia em conjunto com alocao dinmica. O exemplo seguinte mostra um casoonde esta cpia oferecida pelo compilador segura, o tpico seguinte 1.5.3.4 mostra um caso onde esta cpia no segura, leia ambos para ter uma viso geral do assunto:

    #include

    class vetor_tres{

    public:

    int vet[3];

    //vetor alocado estaticamente numa classe.

    vetor_tres(int a,int b,int c)

    { vet[0]=a; vet[1]=b; vet[2]=c; }

    //construtor do vetor

    void mostra(void)

    { cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    43/188

  • 8/8/2019 Tutorial c++ [Unicamp]

    44/188

    vet=new int[tamanho];

    //alocando vetor de "tamanho" posicoes comecando em a[0]

    for (int i=0;i

  • 8/8/2019 Tutorial c++ [Unicamp]

    45/188

    int* a=new int[10];

    A faixa de ndices teis do vetor novamente vai de 0 at (10-1) ou (n-1).

    1.5.3.5. COPIA DE OBJETOS COM VETORES ALOCADOS DINAMICAMENTE.

    Essa determinao do tamanho do vetor em tempo de execuo vai tornar a cpia de objetos feita pelo compiladordiferente, ele vai copiar o ponteiro para o vetor, ou seja os objetos passam a compartilhar a estrutura na memria, o

    que nem sempre pode ser desejvel! Existem maneiras de redefinir esta cpia feita pelo compilador o que veremosem 0.

    #include

    class vetor_tres

    {

    public:

    int* vet;

    //vetor alocado estaticamente numa classe.

    vetor_tres(int a,int b,int c)

    {

    vet=new int[3];

    vet[0]=a;

    vet[1]=b;

    vet[2]=c;

    }

    //construtor do vetor

    void mostra(void)

    { cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    46/188

    v2.mostra();

    //mostrando o conteudo de v2.

    v2=v1;

    //atribuindo objeto v1 ao objeto v2.

    v2.mostra();

    //mostrando v2 alterado.

    v1.vet[0]=44;

    v1.mostra();

    //mostrando o conteudo de v1.

    v2.mostra();

    //mostrando o conteudo de v2.

    }

    Resultado do programa:

    1 2 3

    15 16 17

    1 2 3

    44 2 3

    44 2 3

    Comentrios:

    Note que quando alteramos a cpia de v1, v1 se altera. Isto ocorre porque o vetor no copiado casa a casa comoem 1.5.3.3, s se copia o ponteiro para a posio inicial do vetor, a partir do qual se calcula os endereos das

    posies seguintes v[3]==*(v+3).

    Sobre o texto acima: "a partir do qual se calcula os endereos das posies seguintes", veja o programa exemplo:

    #include void main()

    {

    int* v;

    v=new int[3];

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    47/188

    //*(v)==v[0] uma expressao sempre verdadeira

    }

    Resultado do programa:

    152

    152

    Comentrios:

    O que importante deste exerccio que s se armazena a posio inicial do vetor, as outras posies so calculadascom base no tamanho do tipo alocado e regras de aritmtica de ponteiros. No podemos nos estender muito nestetema, leia sobre aritmtica de ponteiros, porm para este tutorial, basta usar os vetores de forma que esta aritmticafique por conta da linguagem.

    Vetores alocados dinamicamente e ponteiros so a mesma coisa, isto pode ser visto nesse programa exemplo quemistura a sintaxe de vetores e de ponteiros.

    1.5.3.6. TAD E ALOCAO DINMICA.

    Tipo abstrato de dados vetor.

    Um dos grandes problemas de trabalhar com vetores comuns de C++ ( int * a; a=new int[10]; a[22]=3; ) que freqentemente lemos ndices invlidos, ou pior gravamos encima deles.

    Gravar encima de um ndice fora dos limites de um vetor um erro freqente em programao C++. Saiba quefazendo isso voc pode estar apagando instrues de outros programas na memria e outras informaesimportantes! Em alguns casos quando isso ocorre obtm-se inclusive mensagens do sistema operacional avisandoque algo est errado e que necessrio reinicializar a mquina.

    Curiosidade:

    Houve um caso de vrus na internet que se baseava no acesso a ndices fora de um vetor para gravar por cima deinstrues do sistema operacional, cdigo que garantisse a sua multiplicao.

    Algumas linguagens de programao como Pascal e Mdula-3 checam os ndices para que no se acesse reasinvlidas de um vetor. Mdula-3 fornece inclusive os limites dos vetores simples da linguagem atravs de chamadaslast(vetor) ou first(vetor) . Em C++ tal tipo de checagem pode ser implementada pelo programador comofaremos neste exemplo.

    Dica de Programao:

    Lembre-se: seu sucesso em programao vai depender em muito de sua disciplina e organizao tenha sempre emmente que C++ uma linguagem poderosa e que se no usada corretamente pode criar transtornos e erros noperceptveis em testes do programa.

    No checar os ndices de um vetor em programas grandes como instalar uma bomba relgio em seu cdigo, muitoprovvel que em algum instante voc ou at mesmo outra pessoa usando seu programa se distraia e acabe porescrever uma rotina que acessa um ndice invlido de um vetor, fazendo na maioria das vezes o programa falhar.

    A proposta deste exemplo criar um tipo abstrato de dados vetor com uma interface flexvel que sirva para vriasaplicaes e possa ser facilmente estendida. Este exemplo simples e vai ser reapresentado com muitas melhorias nodecorrer do tutorial, dentre elas: "templates" 4.3, "exception handling" 4.5, e a criao de uma classe iterador para ovetor4.1 . A primeira vista voc pode achar que este programa no oferece muito mais que o uso comum de vetores

    em C++, mas com as melhorias que apresentaremos, certamente voc vai preferir representar vetores como tiposabstratos de dados ou TAD's.

    //file exvet1.h

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    48/188

    //header file para classe vetor

    const int inicio=0;

    class vetor{

    private:

    int* v;

    //este e' o vetor

    int tamanho;

    //tamanho maximo do vetor,

    public:

    vetor (int tam);

    //construtor, aloca memria para o vetor.

    void atribui(int index,int valor);

    //altera uma posicao do vetor

    int conteudo(int index);

    //retorna conteudo de posicao do vetor

    int maximo(void);

    //retorna o maior elemento do vetor

    int primeiro(void);

    //primeiro indice do vetor

    int ultimo(void);

    //ultimo indice do vetor

    ~vetor() {delete v;}

    //inline function ou use delete v[];

    };

    //codigo, implementacao, para o header file

    #include

    #include

    #include "exvet1.h"

    vetor::vetor (int tam)

    {v=new int[tam]; tamanho=tam;}

    void vetor::atribui(int index,int valor)

    {

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    49/188

    if (index=inicio)

    v[index]=valor;

    }

    int vetor::conteudo(int index)

    {

    if (index>=tamanho || index

  • 8/8/2019 Tutorial c++ [Unicamp]

    50/188

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    51/188

    2) Implemente uma funo membro chamada ordena para o tipo abstrato de dados vetor definido acima. Usequalquer algoritmo de ordenao.

    3)Crie destrutores para as classes que voc j implementou, mesmo que elas no tenham atributos que usemalocao dinmica. Introduza mensagens tipo cout dd onde -> uma seta, ou flecha que voc pode ler como "oapontado" novamente.

    Os parnteses em (*a).dd so necessrios devido a precedncia do operador. com relao ao *.

    1.5.4. REFERNCIA &

    Aqui vou ensinar passagem por referncia, lembre-se que objetos so passados por referncia, porque eles soreferncia, ponteiros.

    Este tpico vai explicar como usar o operador &, tambm chamado de operador "endereo de...". Este operadorfornece o endereo, a posio na memria de uma varivel, de um argumento, etc. Sua utilizao muito simples, sea uma varivel inteira, &a retorna um ponteiro para a.

    O programa a seguir ilustra a sintaxe do operador:

    #include

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    52/188

    void main()

    {

    int a;

    a=10;

    int* p;

    p=& a;

    (*p)=13;

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    53/188

    {

    int aux=a;

    a=b;

    b=aux;

    }

    //segunda funcao que usa passagem por referencia

    void main()

    {

    int i1=10;

    int i2=20;

    incrementa(i1);

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    54/188

    representao interna. Vamos ver como isso feito usando as palavras reservadas private e public , conceitosde agregao e reuso de cdigo de uma classe matriz.Alm disso usamos const para garantir a integridade da matrizdo quebra-cabea.

    Veja tambm que estamos abordando o tpico representao, no raro voc ter que modelar objetos querepresentem algo do mundo real como motor, quebra-cabea, conta bancria, circuito eltrico e assim por diante.Outros objetos podem ser mais abstratos, exemplo: rvore binria.

    Mais sobre as regras:

    Voc concorda que dada uma situao onde o espao vazio se encontra no meio do quebra-cabea dado comoexemplo o usurio s tem 4 opes? So elas: mover para cima (funo membro movecima), mover para baixo ,mover para a esquerda ou ento para a direita. Note que essas funes membro s trocam peas vizinhas, isso importante pois provado matematicamente que algumas trocas de peas distantes ("Odd permutations") podemtornar o quebra-cabea insolvel. Isto facil de ser verificado para um quebra cabea 2x2.

    Garantimos a soluo do quebra-cabea pelo caminho inverso do embaralhamento das peas, que parte do quebra-cabea solucionado e aplica aleatoriamente sequncias de movimentos iguais aos que o usurio usa para solucionar o

    jogo.

    A matriz bidimensional representada linearmente (vetor) e as funes membro de converso de ndice linear paracolunas e/ou linhas e atribuies so fornecidas, mas somente as necessrias para o jogo .

    Recursos utilizados:

    Argumentos de linha de comando, funes de converso da stdlib, representao linear de uma matriz, const.

    Argumentos de linha de comando:

    Voc pode fazer programas que aceitem argumentos de linha de comandos, resultando em algo equivalente a:

    dir /w //dos

    format A: //dosou ls -la //unix

    Esses argumentos podem ficar disponveis na chamada da funo main de seu programa como os parmetros"argument counter" e "argument values", veja trecho de programa abaixo.

    void main(int argc, char *argv[]) {.../*use argv e argc*/ ...}

    argc um inteiro

    argv um vetor dechar* contendo os argumentos passados. (/w ...)

    argv [0] o nome do programa chamado.

    A faixa til de argvalues : argv[1]...argv[argc-1]

    Portanto se argc==2, temos um nico argumento de linha de comando, disponvel como string em argv[1] . Faaalguns testes com o mesma main usada no programa abaixo e alguns cout's imprimindo os argumentos paraentender melhor o assunto.

    Const:

    J exemplificado em 1.5.1

    Representao linear de uma matriz:

    Pode-se representar uma matriz de qualquer dimenso em um vetor. Veja o exemplo de uma matriz bidimensional deinteiros mostrada no formato indicelinear:valor armazenado

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    55/188

    Vantagem da representao linear (vetor): para referenciar uma posio gasta-se somente um inteiro contra dois darepresentao matriz (linha,coluna). Podemos agora considerar posies que apontam para outras posies, bastainterpretar o contedo do vetor como um ndice linear.

    Desvantagem da representao linear (vetor): necessrio criar funes de converso de ndice na forma(linha,coluna) para (ndice linear) e de (ndice linear) para (coluna) ou (linha). Veja as funes lin e col e lineardo exemplo seguinte.

    Funes de converso da Stdlib:

    A funo int atoi(char* a) converte uma string para um inteiro.

    #include

    class matriz //quebra cabeca de tijolos deslizantes

    {

    private:

    int linhas; //numero de linhas da matrizint colunas; //numero de colunas na matriz

    int tam; //=linhas*colunas

    int *lc; //vetor de tamanho linha*colunas representando matriz:0..(tam-1)

    public:

    matriz(const int l,const int c); //cria matriz LxC

    //qualquer uma das funcoes abaixo retorna nil se nao conseguiu

    int* linear(const int lin,const int col)const ; //ind linear a partir de linha e coluna

    int* col(const int indlin)const ;//coluna a partir do indice linear

    int* lin(const int indlin)const ; //linha a partir do indice linear

    int trocaindlin(const int i,const int j); //argumentos: 2 indices lineares

    //retorna 1 conseguiu, 0 nao conseguiu

    int atribuiindlin(const int i,const int v); //atribui v ao indice i

    //retorna 1 conseguiu, 0 nao conseguiu

    int* retornaindlin(const int i); //retorna conteudo do indice i

    //retorna nil se nao conseguiu

    int getl(void); //retorna numero de linhas

    int getc(void); //retorna numero de colunas

    int gett(void); //retorna tamanho = linhas*colunas

    ~matriz();

    };

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    56/188

    #include "matriz.h"

    matriz::matriz(const int l,const int c) //cria matriz

    {

    lc=new int[l*c]; //l,c dimensoes ; lc vetor[l*c]

    linhas=l;

    colunas=c;

    tam=linhas*colunas;

    }

    int* matriz::linear(const int alin,const int acol) const

    //ind linear a partir de linha e coluna

    {

    int* result=new int; //valor de retorno

    if ( (0

  • 8/8/2019 Tutorial c++ [Unicamp]

    57/188

    int* matriz::lin(const int indlin)const //linha a partir do indice linear

    {

    int* result=new int;

    if ( (0

  • 8/8/2019 Tutorial c++ [Unicamp]

    58/188

    else return 0; //falhou

    }

    int* matriz::retornaindlin(const int indlin)

    //retorna nil se nao conseguiu

    {

    int* result=new int;

    if ( (0

  • 8/8/2019 Tutorial c++ [Unicamp]

    59/188

    #include //formatar cout output com >> setwidth()

    #include //uso rand() em embaralha

    #include //atoi() para converter argumentos de linha de comando

    #include "matriz.h"

    const int min_lado=2; //minimo tamanho lateral do quebracab.

    const int tam_padrao=5; //tamanho padrao

    class quebracab //quebra cabeca de tijolos deslizantes

    {

    private:

    int vazio; //indice linear da casa vazia

    int mov; //numero de movimentos

    matriz* mqc; //matriz interna do quebra cabecas

    public:

    quebracab(const int ld=tam_padrao); //cria quebra cabeca, ld=lado

    void mostra() const; //mostra quebra cabeca

    void movedir(); //move celula a esq de vazio para direita.

    void moveesq(); //analogo

    void movebaixo(); //analogo

    void movecima(); //analogo

    void embaralha(); //embaralha quebracabeca

    int tstsolucao() const; //testa se quebracabeca esta solucionado

    int retorna_mov() { return mov; } //retorna numero de movimentos

    ~quebracab(); //destroi quebra cabecas

    };

    quebracab::quebracab(const int ld) //argumento padrao desnessario, ja declarado

    {

    int ldc=abs(ld); //ld copia = valor positivo de ld

    if (ldcatribuiindlin(i,i); //initializa casas da matriz

    mqc->atribuiindlin(mqc->gett(),0);//atribui zero a posicao da celula vazia

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    60/188

    vazio=mqc->gett(); //define posicao da celula vazia

    mov=0; //sem nenhum movimento

    embaralha(); //embaralha quebracabeca

    }

    void quebracab::mostra() const //mostra quebra cabeca

    {

    int i,j; //linha e coluna

    int* ind; //valor atual

    for(i=1;igetl();i++) //loop das linhas

    { //linhas

    for(j=1;jgetc();j++) //loop das colunas

    { //colunas

    ind=mqc->linear(i,j); //resultado tambem e ponteiro

    if

    ((*ind)==vazio) cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    61/188

    void quebracab::moveesq() //espaco move para direita

    {

    if ( (*(mqc->col(vazio)))!=mqc->getc() ) /*nao esta na borda direita*/

    {

    mqc->trocaindlin(vazio,vazio+1);

    mov++;

    vazio=vazio+1;

    }

    }

    void quebracab::movebaixo() //espaco move para cima

    {

    if ((*(mqc->lin(vazio)))!=1) /*nao esta no topo*/

    {

    mqc->trocaindlin(vazio,vazio-(mqc->getc())); //chama funcao private

    mov++;

    vazio=vazio-(mqc->getc());

    }

    }

    void quebracab::movecima() //espaco move para baixo

    {

    if ((*mqc->lin(vazio))!=mqc->getl()) /*nao esta em baixo*/

    {

    mqc->trocaindlin(vazio,vazio+(mqc->getc()));

    mov++;

    vazio=vazio+(mqc->getc());

    }

    }

    void quebracab::embaralha() //embaralha quebracabeca

    {

    int i,j; //loop principal, loop secundario

    int r; //r times

    for(j=0;jgett();j++)

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    62/188

    {

    r=(rand()% mqc->getc());

    for(i=0;imovedir();} //move r vezes

    r=(rand()% mqc->getl());

    for(i=0;imovebaixo();}

    r=(rand()% mqc->getc());

    for(i=0;imoveesq();}

    r=(rand()% mqc->getl());

    for(i=0;imovecima();}

    }

    mov=0; //inicializa movimentos

    }

    int quebracab::tstsolucao() const //testa se quebracabeca esta solucionado

    {

    int i=1,cont=1;

    while( cont && (i< (mqc->gett()) ) )

    {

    if ((*(mqc->retornaindlin(i)))==(i)) cont=1; else cont=0;

    i++;

    }

    return (cont); //i=qctam esta solucionado 1 2 3... 24 0

    }

    quebracab::~quebracab()

    {if (mqc!=NULL) delete mqc; cout 1) ladocomp=atoi(argv[1]);

    //convertendo argumento de linha de comando para inteiro

    else ladocomp=tam_padrao; //valor default

    quebracab aquebracab(ladocomp); //criando quebracab

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    63/188

    do {

    aquebracab.mostra();

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    64/188

    Comentrios:

    delete []qc; Este destrutor adota uma tcnica diferente para deleo de vetores, cheque que tcnicas seucompilador suporta.

    Exerccios:

    1) Se voc implementou o jogo de quebra-cabea notar que no existe apagamento da tela, somente "scroll". Istotorna o jogo um pouco cansativo porque d para ver o quebra cabea sendo empurrado para o alto da tela e a nova

    representao sendo criada na parte de baixo do "display". A razo de tal escolha simples: a funo de apagamentode tela do DOS no portvel para o UNIX e vice versa. Descubra a funo de CLS (Clear Screen) do seu ambientede programao e use-a no programa. Numa segunda etapa introduza cores no programa, voc pode usar a funomdulo (nmero da pea ,nmero de cores) para determinar a cor de uma pea.

    2) Implemente outros jogos simples. Pense em jogos compatveis com a sua experincia. Aqui vo algumassugestes:

    Senha: Jogo bastante conhecido, o programa cria um cdigo de n dgitos e m smbolos. Atravs de chutes o jogadortenta acertar o cdigo na seqncia. A cada chute o programa da dicas dos acertos sendo elas de dois tipos: Acertouo smbolo X vezes ou acertou o smbolo e a posio Y vezes. Voc ter que usar uma funo para obter nmerosaleatrios, provavelmente rand da "library" .

    Jogo da velha.

    Se voc no conhece os jogos procure obter mais informaes antes de comear a implementa-los.

    5)Melhore a classe matriz para aceitar nas suas funes argumentos do tipo (linha,coluna) e no s ndices lineares.

    4) Construa um programa simples que recebe argumentos da linha de comando e os imprime atravs de cout.Normalmente isso que deve ser feito antes de usar um recurso da linguagem pela primeira vez, experimenta-lo emprogramas simples.

    2. HERANA2.1. HIERARQUIAS DE TIPOS

    Neste tpico mostraremos como construir hierarquias de tipo por generalizao / especializao.

    2.1.1. UMA HIERARQUIA SIMPLES.

    Construiremos uma hierarquia de tipos simples para demonstrar herana pblica em C++.

    Comentrios:

    O diagrama acima representa a hierarquia de classes implementada e foi obtido a partir da janela de edio de umaferramenta case para programao orientada a objetos.

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    65/188

    A classe ponto que est no topo da hierarquia chamada de classe base, enquanto que as classes ponto_reflete eponto_move so chamadas classes filhas ou herdeiras.As classes da hierarquia so simples, ponto_move apresentaa funo membro move, j vista neste tutorial em 1.2.6, ponto_reflete apresenta a funo membro (reflete)que inverte o sinal das coordenadas.

    Dada a simplicidade das classes o leitor poderia se perguntar, porque no juntar

    as trs em uma s . A pergunta faz sentido, mas e se quisssemos criar uma classe ponto que no se movesse, apenasrefletisse e outra que s se movesse? E se quisssemos projetar nosso programa segundo uma hierarquia deespecializao / generalizao da classe ponto? O exemplo mostra como faz-lo.

    Herana Pblica:

    Na herana pblica as classes filhas passam a ter as mesmas funes membro public da classe pai, as classes filhaspodem acrescentar funes membro, dados membro e at redefinir funes membro herdadas (veremos mais tarde).Os atributos da classe pai no so acessveis diretamente na classe filha a no ser que sejam qualificados comoprotected, veja 2.1.2. Por isso que se diz que as classes filhas garantem pelo menos o comportamento"behaviour" da classe pai, podendo acrescentar mais caractersticas.

    Diagrama de acesso, visibilidade, de dados membro e funes membro de uma classe pai para uma classe filha ouherdeira por herana pblica:

    Construtores e herana:

    No construtor de uma classe filha o programador pode incluir a chamada do construtor da classe pai.

    Destrutores e herana:

    Quando um objeto da classe derivada destrudo, o destrutor da classe pai tambm chamado dando a oportunidadede liberar a memria ocupada pelos atributos private da classe pai.

    //header file

    class ponto

    {

    private:

    float x; //sao ocultos por default

    float y; //sao ocultos por default

    public: //daqui em diante tudo e acessivel.

    ponto(float a,float b);

    void inicializa(float a,float b);

    float retorna_x(void);

    float retorna_y(void);

    void altera_x(float a);

    void altera_y(float b);

    void mostra(void);

    };

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    66/188

  • 8/8/2019 Tutorial c++ [Unicamp]

    67/188

    { y=b; }

    void ponto::mostra(void)

    {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    68/188

  • 8/8/2019 Tutorial c++ [Unicamp]

    69/188

    void inicializa(float a,float b);

    float retorna_x(void);

    float retorna_y(void);

    void altera_x(float a);

    void altera_y(float b);

    void mostra(void);

    };

    class ponto_reflete:public ponto

    {

    private:

    //se voce quer adicionar dados membro encapsulados...

    public:

    ponto_reflete(float a, float b);

    void reflete(void);

    };

    class ponto_move:public ponto

    {

    public:

    ponto_move(float a,float b);

    void move(float dx,float dy);

    };

    //implementation file

    #include

    #include "pontos.h"

    ponto::ponto(float a,float b)

    {

    inicializa(a,b);

    }

    void ponto::inicializa(float a,float b)

    {

    x=a;

    y=b;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    70/188

    }

    float ponto::retorna_x(void)

    { return x; }

    float ponto::retorna_y(void)

    { return y; }

    void ponto::altera_x(float a)

    { x=a; }

    void ponto::altera_y(float b)

    { y=b; }

    void ponto::mostra(void)

    {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    71/188

    {

    ponto_reflete p1(3.14,2.17);

    p1.reflete();

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    72/188

    float retorna_x(void);

    float retorna_y(void);

    void altera_x(float a);

    void altera_y(float b);

    void mostra(void);

    };

    class ponto_reflete:public ponto

    {

    private:

    //se voce quer adicionar dados membro

    public:

    ponto_reflete(float a, float b);

    void reflete(void);

    void mostra(void);

    //redefinicao

    };

    class ponto_move:public ponto

    {

    public:

    ponto_move(float a,float b);

    void move(float dx,float dy);

    //esta classe filha nao redefine mostra

    };

    //implementation file

    #include

    #include "pontos.h"

    ponto::ponto(float a,float b)

    {

    inicializa(a,b);

    }

    void ponto::inicializa(float a,float b)

    {

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    73/188

    x=a;

    y=b;

    }

    float ponto::retorna_x(void)

    { return x; }

    float ponto::retorna_y(void)

    { return y; }

    void ponto::altera_x(float a)

    { x=a; }

    void ponto::altera_y(float b)

    { y=b; }

    void ponto::mostra(void)

    {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    74/188

    altera_x(retorna_x()+dx);

    altera_y(retorna_y()+dy);

    }

    #include

    #include "pontos.h"

    void main()

    {

    ponto_reflete p1(3.14,2.17);

    p1.reflete();

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    75/188

    fila.

    #ifndef MLISTH_H

    #define MLISTH_H

    #include

    #include

    //Criacao de uma hierarquia de listas ligadas.

    //O elemento da lista e' um inteiro

    enum Boolean{FALSE,TRUE};

    class no{ //este e' o no da lista ligada, so e' usado por ela

    private:

    int info; //informacaono* prox; //ponteiro para o proximo

    public:

    no();

    no(int i,no* p);

    no* get_prox(void);

    void set_prox(no* p);

    int get_info(void);

    void set_info(int i);

    no* dobra(void);

    ~no(void);

    } ;

    class lista{ //esta e' a lista ligada comum.

    protected: //"visivel hierarquia abaixo"

    no* primeiro; //primeiro no da lista, aqui eu insiro e removo.

    public:

    lista(void);

    Boolean vazia(void)const;

    Boolean contem(int el)const;

    void insere_primeiro(int elem);

    int* remove_primeiro();

    void mostra()const;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    76/188

    ~lista(void);

    }; //fim classe lista

    class listaultimo:public lista { //essa e a lista util para

    //implementar pilhas e filas.

    protected: //protected e uma opcao outra e' get_ultimo() e set_...

    no* ultimo;

    public:

    listaultimo(void);

    void insere_ultimo(int elem); //nova

    void insere_primeiro(int elem); //redefinicao

    int* remove_primeiro();//redefinicao

    ~listaultimo(void);

    //as operacoes nao redefinidas sao validas.

    };

    class listaordenada:public lista {

    //essa e' a lista comum com aprimoramentos/especializacoes

    public:

    listaordenada(void);

    Boolean contem(int el)const;

    void insere_primeiro(int elem);

    //insere em ordem

    int* remove_elemento(int el);

    //remove elemento el se existir

    ~listaordenada(void);

    };

    #endif

    #include "mlisth.h"

    #include

    #include

    no::no()

    {prox=NULL;cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    77/188

    {info=i;prox=p;cout get_prox()->dobra());

    //recursividade para duplicacao da lista

    }

    no::~no(void) {cout get_info()!=el)

    {if (curr->get_prox()==NULL) Conti=FALSE; else curr=curr->get_prox();}

    else

    Conti=FALSE;

    }; //while

    return Boolean(curr->get_info()==el);

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    78/188

    };

    void lista::insere_primeiro(int elem)

    {

    no* insirame;

    if (primeiro==NULL) //lista vazia

    primeiro=new no(elem,NULL);

    else {

    insirame=new no(elem,primeiro);

    primeiro=insirame;

    };

    };

    int* lista::remove_primeiro()

    {

    int* devolvame=new int; //return

    no* temp; //to delete

    if (primeiro==NULL) return NULL; //lista vazia

    else {

    (*devolvame)=primeiro->get_info();

    temp=primeiro;

    primeiro=primeiro->get_prox();

    delete temp;

    return devolvame;

    };

    };

    void lista::mostra() const

    {

    no* curr;

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    79/188

    curr=curr->get_prox();

    };

    }

    lista::~lista(void)

    {

    no* temp;

    while (primeiro!=NULL)

    {

    temp=primeiro;

    primeiro=primeiro->get_prox();

    delete temp;

    };

    }

    listaordenada::listaordenada(void):lista()

    {};

    Boolean listaordenada::contem(int el)const

    {

    no* curr;

    Boolean conti=TRUE;

    curr=primeiro;

    while ((curr!=NULL) && conti)

    {

    if (curr->get_info()get_prox();

    else conti=FALSE;

    };

    if (curr==NULL) return FALSE;

    else return Boolean(curr->get_info()==el);

    }

    void listaordenada::insere_primeiro(int elem)

    {

    no* curr=primeiro;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    80/188

    no* prev=NULL;

    no* insirame;

    Boolean conti=TRUE;

    while ((curr!=NULL) && conti)

    {

    if (curr->get_info()get_prox();}

    else conti=FALSE;

    };

    insirame=new no(elem,curr);

    if (prev==NULL) primeiro=insirame;

    else prev->set_prox(insirame);

    }

    int* listaordenada::remove_elemento(int el)

    {

    int* devolvame=new int;

    no* curr=primeiro;

    no* prev=NULL;

    no* deleteme;

    Boolean conti=TRUE;

    while ((curr!=NULL) && conti) //acha lugar onde pode estar el

    {

    if (curr->get_info()get_prox();} //anda

    else conti=FALSE;

    };

    if (curr==NULL) return NULL; //fim de lista ou vazia

    else //pode ser o elemento ou ele nao existe

    {

    if (curr->get_info()==el)

    {

    deleteme=curr;

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    81/188

    if (prev==NULL) //lista so com um elemento ou primeiro el

    primeiro=curr->get_prox();

    else

    {

    prev->set_prox(curr->get_prox());

    }

    (*devolvame)=deleteme->get_info(); //so para verificar

    delete deleteme;

    return devolvame;

    }

    else return NULL;

    }

    }

    listaordenada::~listaordenada(void)

    {cout set_prox(insirame);

    ultimo=insirame;

    };

    if (primeiro==NULL) primeiro=ultimo; //lista vazia

    }

    void listaultimo::insere_primeiro(int elem) //redefinicao

    {

    TORIAL: http://www.ic.unicamp.br/~cmrubira/aacesta/cpp/cpp15.html

    de 188 07/05/2010 01:11

  • 8/8/2019 Tutorial c++ [Unicamp]

    82/188

  • 8/8/2019 Tutorial c++ [Unicamp]

    83/188

    delete temp;

    };

    delete ultimo;

    }

    #include "mlisth.h"

    main()

    {

    listaordenada minha;

    char option; //use in menu as option variable

    int el; //elemento a inserir

    int* receptor;do {

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    84/188

    case 'P':

    case 'p':

    cout > el;

    minha.insere_primeiro(el);

    break;

    case 'R':

    case 'r':

    if (!minha.vazia())

    cout

  • 8/8/2019 Tutorial c++ [Unicamp]

    85/188

    Note que o programa principal s testa a lista ordenada, em outros programas exemplo baseados neste veremostestes para a lista_ultimo.

    Exerccios:

    1)Experimente derivar (criar classes herdeiras) outras classes lista com propriedades de seu interesse tais comoobteno de sublista.

    2)Introduza na classe lista a contagem do nmero de elementos numa lista.

    3)Crie uma funo membro chamado void remove_todos(void); que simplesmente deixa a lista vazia.

    *4)Suponha que voc um programador de uma empresa e teve que implementar a hierarquia de listas para seugrupo de desenvolvimento, segundo uma especificao dada pelo seu chefe.

    Voc introduziria as mudanas sugeridas nos exerccios anteriores, mesmo sabendo que elas no estavam naespecificao? Que dificuldade um usurio de sua classe lista teria para introduzi-las caso surgisse a necessidade evoc no tivesse feito?

    Discuta as seguintes maneiras de um programador de seu grupo conseguir o efeito desejado de adicionar as sugestesdos exerccios anteriores a hierarquia: usar herana (derivar uma classe com void remove_todos(void) ), alterar

    o cdigo original, pedir para voc o programador do cdigo original mudar a implementao. Lembre-se que podeexistir mais de um programador usando a verso original da hierarquia de listas.

    2.2. HIERARQUIAS DE IMPLEMENTAO