Ir ao conteúdo

Posts recomendados

Postado

Vi uma questão sobre herança. Como aprendo agora, estou treinando. A questão pedia para criar uma classe Tataravô e as seguintes, Bisavô, Avô, Pai, Filho e Neto tem de herdar de Tataravô. Só que não saquei o lance da questão, por que Bisavô é filho, Avô também é filho etc...

Isso é herança múltipla, mulitlevel, tenho de usar ponteiros?

Eu parti fazendo bem simples com Avô, Pai e Filho.

Corrijam meus erros...

Valeu

#include <iostream>

using namespace std;

class Avo{
public:
    int idade, carros, casas;
//CONSTRUTOR
    Avo(int i, int car, int cas);
    /*DESTRUTOR
    ~Avo(){
        cout << "Vazio" << endl;
    }
    */
//SETTERS AND GETTERS
    void setsalario(int s){
        salario = s;
    }
    int getsalario(){
        return salario;
    }
    void setprofissao(string p){
        profissao = p;
    }
    string getprofissao(){
        return profissao;
    }
private:
    int salario;
    string profissao;
};

//DEFININDO O CONSTRUTOR FORA DA CLASSE
Avo::Avo(int i, int car, int cas){
    idade = i;
    carros = car;
    casas = cas;
    }
//HERANCA (CLASSE DERIVADA)
class Pai: public Avo{
public:
    int idade, carros, casas;
};

class Filho: public Avo{
public:
    int idade, carros, casas;
};

int main()
{
    //DADOS AVO
    cout << "Avo - Caracteristicas" << endl;
    Avo geracao1(65,6,4);
    cout << "Idade: " << geracao1.idade << " Carros: " << geracao1.carros << " Casas: " << geracao1.casas << endl;
    cout << "Salario: ";
    geracao1.setsalario(10000);
    cout << geracao1.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao1.setprofissao("Engenheiro");
    cout << geracao1.getprofissao();
    //DADOS PAI
cout << "Avo - Caracteristicas" << endl;
    Pai geracao2(40,3,2);
    cout << "Idade: " << geracao2.idade << " Carros: " << geracao2.carros << " Casas: " << geracao2.casas << endl;
    cout << "Salario: ";
    geracao2.setsalario(7000);
    cout << geracao2.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao2.setprofissao("Analista de Sistemas");
    cout << geracao2.getprofissao();

    //DADOS FILHO
    cout << "Avo - Caracteristicas" << endl;
    Filho geracao3(23,1,1);
    cout << "Idade: " << geracao3.idade << " Carros: " << geracao3.carros << " Casas: " << geracao3.casas << endl;
    cout << "Salario: ";
    geracao3.setsalario(3000);
    cout << geracao3.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao3.setprofissao("Professor");
    cout << geracao3.getprofissao();
    return 0;
}

 

Postado

@TomJohn Bom Dia!

Acredito que a class Pai/filho esteja no centro das heranças.

 

3jMm8wA6sZqcVpSHRk2mO9B8Ycr1W4hoEoxGgSfO

Veja um limite em sua lógica!

1 hora atrás, TomJohn disse:

Só que não saquei o lance da questão, por que Bisavô é filho, Avô também é filho etc...

 

Exatamente, talvez esteja aí o seu engano (do meu ponto de vistas) você não precisa se preocupar com a classe pai do Bisavô (Trisavô), caso contrário é uma curva sem fim.  

 

Todos são pais exceto o neto ou ainda todos são filhos exceto o Bisavô, qualquer um dos pensamentos conduz a resposta, logo os dois estão certos (até que se prove o contrário para uma deles).

 

O mais correto é: Todos são pais ... exceto o neto do pai! 

Bisavô (Alto)

     ↳     Avô (Olhos castanhos)

               ↳  Pai (Pele clara)

                     ↳  Filho (Dente de coelho)

                            ↳   Neto (Mãos Grandes)

 

O Neto é alto de olhos castanhos com pele clara e um sorriso de coelho com mãozada boa.

 

Postado
4 horas atrás, TomJohn disse:

A questão pedia para criar uma classe Tataravô e as seguintes, Bisavô, Avô, Pai, Filho e Neto tem de herdar de Tataravô. Só que não saquei o lance da questão, por que Bisavô é filho, Avô também é filho etc...

Isso é herança múltipla, mulitlevel, tenho de usar ponteiros?

 

herança múltipla seria o caso de uma classe ser derivada de mais de uma outra

 

Multilevel eu não sei o que é, talvez você pudesse dar uma referência de onde leu isso

 

Ponteiros não tem a ver com classes. Sua lógica vai determinar, quando for declarar uma variável de uma classe, se vai declarar um ponteiro para a classe ou alocar uma instância diretamente, como em

Avo    pai_da_Claudia;
Avo*   um_avo;

Como sempre sugiro, não use menus e cout e campos diversos enquanto está resolvendo um exercício ou aprendendo um conceito: nada acrescenta ao caso o fato de um avo ter idade e carros. Depois que você entender você agrega essas coisas em minutos. Use um único atributo como

int    ID;    // ou 
string nome;

e implemente a s classes

 

Herança:

 

Quando uma classe é derivada de outra, herdada, herda todos os métodos e atributos.. Se você redeclara todos ela herda, mas não herda nada: some tudo. Você teria que usar artifícios para acessar a idade do pai por exemplo, porque você redefiniu idade para o filho... Pense nisso: herdar é para estender com novos métodos ou campos, ou redefinir métodos importantes. Em java se usa inclusive extends ao invés do ´: ´ que se usa em C++

 

4 horas atrás, TomJohn disse:

não saquei o lance da questão, por que Bisavô é filho, Avô também é filho

 

Não mostrou a questão... Mas entenda que filho é outra relação.Teria que pensar em uma classe que expressasse isso. Esse exemplo de herdar a partir de Pai ou de Adulto ou de Descendente é muito comum nos livros, mas não é nada feliz. Seria melhor ficar com os exemplos de carro ou animal por exemplo :D Esses sim tem uma derivação que dá pra entender melhor. Minha opinião, de todo modo

 

EXEMPLO

 

Vou te mostrar um programa, cuja saída está abaixo, e que vai ilustrar melhor o que acontece, incluindo aí a chamada dos construtores das classes base. Sugiro ler a saída, ler as classes e talvez rodar o programa em seu micro e ir mudando coisas.

 

É muito importante --- veja a classe Neto ---você entender que

  • C++ vai invocar todos os construtores das classes herdadas, na sequência
  • qualquer variável ou método redeclarado vai " esconder"  o que estava na classe base.

 

Eis a saída

 

----- Tataravo
Criando tataravo: nome=Tataravo
tataravo Tataravo
----- Bisavo
Criando tataravo: nome=Bisavo
  Criando bisavo: nome=Bisavo
Bisavo [Bisavo ]
pai de [Bisavo] = [Tataravo]
----- Avo
Criando tataravo: nome=Avo
  Criando bisavo: nome=Avo
    Criando avo: nome=Avo
pai de Avo = Bisavo
----- Pai
Criando tataravo: nome=Pai
  Criando bisavo: nome=Pai
    Criando avo: nome=Pai
      Criando pai: nome=Pai
pai de Pai = Avo
----- Filho
Criando tataravo: nome=Filho
  Criando bisavo: nome=Filho
    Criando avo: nome=Filho
      Criando pai: nome=Filho
        Criando filho: nome=Filho
pai de Filho = Pai
----- Neto
Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto
pai de Neto = Filho

 

Agora a classe Tataravo
 

class Tataravo
{
public:
    string nome;
public:
    Tataravo()    { nome = "bisavo, nome nao informado";    };
    Tataravo(string n)
    {
        nome = n; 
        cout << "Criando tataravo: nome="  << nome << endl;
    };
};    // end class

ATENÇÃO para a classe Bisavo

 

class Bisavo : public Tataravo
{
public:
    string pai;
public:
    Bisavo(){nome = "bisavo, nome nao informado";};
    Bisavo(string n) : Tataravo(n)
    {
        cout << "  Criando bisavo: nome=" << n << endl;
    };
    void nome_do_pai(string n)
    {
        pai = n;        
    };
};    // end class

NOTE

 

A classe bisavô extende a classe base Tataravo, e acrescenta a variável pai e o método nome_do_pai()

com sentido óbvio. Como o Tataravo é o início de tudo, faz sentido inserir essas coisas a partir da segunda geração, certo?

 

e as outras classes?

 

Essas não acrescentam nada no meu exemplo. É só um exemplo rápido afinal. E a ideia não é assim muito boa.

 

Como usa isso?


 

int main()
{
    cout << "----- Tataravo" << endl;
    Tataravo t("Tataravo");
    cout << "tataravo " << t.nome << endl;
     
    cout << "----- Bisavo" << endl;
    Bisavo b("Bisavo");
    b.nome_do_pai(t.nome);
    cout << "Bisavo [" << b.nome << " ]" << endl;
    cout << "pai de [" << b.nome << "] = [" << b.pai << "]" << endl;

    cout << "----- Avo" << endl;
    Avo a("Avo");
    a.nome_do_pai(b.nome);
    cout << "pai de " << a.nome << " = " << a.pai << endl;

    cout << "----- Pai" << endl;
    Pai p("Pai");
    p.nome_do_pai(a.nome);
    cout << "pai de " << p.nome << " = " << p.pai << endl;

    cout << "----- Filho" << endl;
    Filho f("Filho");
    f.nome_do_pai(p.nome);
    cout << "pai de " << f.nome << " = " << f.pai << endl;

    cout << "----- Neto" << endl;
    Neto n("Neto");
    n.nome_do_pai(f.nome);
    cout << "pai de " << n.nome << " = " << n.pai << endl;

}

Apenas declarei um de cada e defini o nome do pai para ilustrar. Não é nada que faça sentido mas já dá pra você entender o mecanismo imagino. Eis o programa todo

#pragma once
#include <iostream>

using namespace std;


class Tataravo
{
public:
    string nome;
public:
    Tataravo()    { nome = "bisavo, nome nao informado";    };
    Tataravo(string n)
    {
        nome = n; 
        cout << "Criando tataravo: nome="  << nome << endl;
    };
};    // end class


class Bisavo : public Tataravo
{
public:
    string pai;
public:
    Bisavo(){nome = "bisavo, nome nao informado";};
    Bisavo(string n) : Tataravo(n)
    {
        cout << "  Criando bisavo: nome=" << n << endl;
    };
    void nome_do_pai(string n) {
        pai = n;
        //cout << "nome_do_pai(): pai de [" << nome << "]=[" << n << "]" << endl;
    };
};    // end class


class Avo : public Bisavo
{
public:
    Avo() { nome = "avo, nome nao informado"; };
    Avo(string n) : Bisavo(n)
    {
        cout << "    Criando avo: nome=" << n << endl;
    };
};    // end class


class Pai : public Avo
{
public:
    Pai() { nome = "avo, nome nao informado"; };
    Pai(string n) : Avo(n)
    { 
        cout << "      Criando pai: nome=" << nome << endl;
    };
};    // end class


class Filho : public Pai
{
public:
    Filho() { nome = "filho, nome nao informado"; };
    Filho(string nome) : Pai(nome) 
    { 
        cout << "        Criando filho: nome=" << nome << endl;
    };
};    // end class


class Neto : public Filho
{
public:
    Neto(){    nome = "neto, nome nao informado";};
    Neto(string nome) : Filho(nome)
    { 
        cout << "          Criando neto: nome=" << nome << endl;
    };
};    // end class


int main()
{
    cout << "----- Tataravo" << endl;
    Tataravo t("Tataravo");
    cout << "tataravo " << t.nome << endl;
     
    cout << "----- Bisavo" << endl;
    Bisavo b("Bisavo");
    b.nome_do_pai(t.nome);
    cout << "Bisavo [" << b.nome << " ]" << endl;
    cout << "pai de [" << b.nome << "] = [" << b.pai << "]" << endl;

    cout << "----- Avo" << endl;
    Avo a("Avo");
    a.nome_do_pai(b.nome);
    cout << "pai de " << a.nome << " = " << a.pai << endl;

    cout << "----- Pai" << endl;
    Pai p("Pai");
    p.nome_do_pai(a.nome);
    cout << "pai de " << p.nome << " = " << p.pai << endl;

    cout << "----- Filho" << endl;
    Filho f("Filho");
    f.nome_do_pai(p.nome);
    cout << "pai de " << f.nome << " = " << f.pai << endl;

    cout << "----- Neto" << endl;
    Neto n("Neto");
    n.nome_do_pai(f.nome);
    cout << "pai de " << n.nome << " = " << n.pai << endl;

}

 

adicionado 5 minutos depois

Um exemplo mínimo:
 

    cout << "----- Neto" << endl;
    Neto n("Neto");
    n.nome_do_pai("Pai do Neto" );
    cout << "pai de " << n.nome << " = " << n.pai << endl;

Mostra 

----- Neto
Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto
pai de Neto = Pai do Neto

 

  • Obrigado 1
Postado

@Mauro Britivaldo @arfneto Opa, valeu pela ajuda. Chego já em casa e releio as respostas.

O enunciado do problema era somente esse:

 

Problema 17

Desenvolva um programa em C++ baseado em uma árvore genealógica. O programa deve conter a classe Tataravô
e as seguintes subclasses Bisavô, Avô, Pai, Filho e Neto devem herdar as características de Tataravô.

 

Então eu tentei me imaginar como seria a resposta. Mas passei longe.

Postado
1 hora atrás, TomJohn disse:

@Mauro Britivaldo @arfneto Opa, valeu pela ajuda. Chego já em casa e releio as respostas.

O enunciado do problema era somente esse:

 

Problema 17

Desenvolva um programa em C++ baseado em uma árvore genealógica. O programa deve conter a classe Tataravô
e as seguintes subclasses Bisavô, Avô, Pai, Filho e Neto devem herdar as características de Tataravô.

 

Então eu tentei me imaginar como seria a resposta. Mas passei longe.

 

Pelo enunciado já se vê onde esse exemplo se encaixaria melhor: no curso de estruturas de dados. Onde tem vetores, listas e... árvores de toda sorte. Herança em programação orientada a objetos está associada à especialização de classes, não a relacionamentos. Mas pode ser feito, afinal é o enunciado.

 

Tem uma inversão de papéis no título do tópico: Herdar da classe base não é causa e sim consequência. Ao derivar uma classe, como Pai, por exemplo, você torna a classe Pai a classe base para Filho. Note que são só nomes. Você pode derivar Pai de Filho igualmente.

 

É essencial você entender que

  • ao declarar uma classe numa hierarquia de classes derivadas o compilador vai gerar código para chamar TODOS os construtores até a classe base da hierarquia. Explícitos ou não.
  • Variáveis e métodos das classes " acima" continuam disponíveis e você só declara outros quando for vantagem ou necessidade
  • Curtir 1
Postado
22 horas atrás, TomJohn disse:

@Mauro Britivaldo @arfneto Opa, valeu pela ajuda. Chego já em casa e releio as respostas.

O enunciado do problema era somente esse:

 

Problema 17

Desenvolva um programa em C++ baseado em uma árvore genealógica. O programa deve conter a classe Tataravô
e as seguintes subclasses Bisavô, Avô, Pai, Filho e Neto devem herdar as características de Tataravô.

 

Então eu tentei me imaginar como seria a resposta. Mas passei longe.

Ah isso mudou bastante.

 

Trisavô (Magro)

↳   Bisavô (Alto)

↳   Avô (Olhos castanhos) 

↳   Pai (Pele clara)

↳   Filho (Dente de coelho)

↳   Neto (Mãos Grandes)

 

O Neto é magro e de mãos grandes.

O Filho é magro e de dente de coelho.

...

O bisavô é magro e alto.

O trisavô é magro.

 

  • Curtir 1
Postado

@arfnetoOpa, agora deu tempo de fazer as correções.

Ficou assim, partindo do simples.

#include <iostream>

using namespace std;

class Avo{
public:
    int idade, carros, casas;
//CONSTRUTOR
public:
    Avo(int i, int car, int cas){
    idade = i;
    carros = car;
    casas = cas;
    };
    /*DESTRUTOR
    ~Avo(){
        cout << "Vazio" << endl;
    }
    */
//SETTERS AND GETTERS
    void setsalario(int s){
        salario = s;
    }
    int getsalario(){
        return salario;
    }
    void setprofissao(string p){
        profissao = p;
    }
    string getprofissao(){
        return profissao;
    }
private:
    int salario;
    string profissao;
};

//DEFININDO O CONSTRUTOR FORA DA CLASSE

//HERANCA (CLASSE DERIVADA)
class Pai: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Pai(int i, int car, int cas):Avo(i, car, cas){

    };
};

class Filho: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Filho(int i, int car, int cas):Avo(i, car, cas){

    };
};

int main()
{
    //DADOS AVO
    cout << "Avo - Caracteristicas" << endl;
    Avo geracao1(65,6,4);
    cout << "Idade: " << geracao1.idade << " Carros: " << geracao1.carros << " Casas: " << geracao1.casas << endl;
    cout << "Salario: ";
    geracao1.setsalario(10000);
    cout << geracao1.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao1.setprofissao("Engenheiro\n");
    cout << geracao1.getprofissao();
    //DADOS PAI
cout << "Pai - Caracteristicas" << endl;
    Pai geracao2(40,3,2);
    cout << "Idade: " << geracao2.idade << " Carros: " << geracao2.carros << " Casas: " << geracao2.casas << endl;
    cout << "Salario: ";
    geracao2.setsalario(7000);
    cout << geracao2.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao2.setprofissao("Analista de Sistemas\n");
    cout << geracao2.getprofissao();

    //DADOS FILHO
    cout << "Filho - Caracteristicas" << endl;
    Filho geracao3(23,1,1);
    cout << "Idade: " << geracao3.idade << " Carros: " << geracao3.carros << " Casas: " << geracao3.casas << endl;
    cout << "Salario: ";
    geracao3.setsalario(3000);
    cout << geracao3.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao3.setprofissao("Professor");
    cout << geracao3.getprofissao();
    return 0;
}

Resultado

Avo - Caracteristicas
Idade: 65 Carros: 6 Casas: 4
Salario: 10000
Profissao: Engenheiro
Pai - Caracteristicas
Idade: 40 Carros: 3 Casas: 2
Salario: 7000
Profissao: Analista de Sistemas
Filho - Caracteristicas
Idade: 23 Carros: 1 Casas: 1
Salario: 3000
Profissao: Professor
Process returned 0 (0x0)   execution time : 0.030 s
Press any key to continue.

Vou ver o que dá pra avançar nisso.

Muito obrigado a todos.

Postado

@TomJohn Boa tarde!

6 horas atrás, TomJohn disse:

@arfnetoOpa, agora deu tempo de fazer as correções.

Ficou assim, partindo do simples.


#include <iostream>

using namespace std;

class Avo{
public:
    int idade, carros, casas;
//CONSTRUTOR
public:
    Avo(int i, int car, int cas){
    idade = i;
    carros = car;
    casas = cas;
    };
    /*DESTRUTOR
    ~Avo(){
        cout << "Vazio" << endl;
    }
    */
//SETTERS AND GETTERS
    void setsalario(int s){
        salario = s;
    }
    int getsalario(){
        return salario;
    }
    void setprofissao(string p){
        profissao = p;
    }
    string getprofissao(){
        return profissao;
    }
private:
    int salario;
    string profissao;
};

//DEFININDO O CONSTRUTOR FORA DA CLASSE

//HERANCA (CLASSE DERIVADA)
class Pai: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Pai(int i, int car, int cas):Avo(i, car, cas){

    };
};

class Filho: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Filho(int i, int car, int cas):Avo(i, car, cas){

    };
};

int main()
{
    //DADOS AVO
    cout << "Avo - Caracteristicas" << endl;
    Avo geracao1(65,6,4);
    cout << "Idade: " << geracao1.idade << " Carros: " << geracao1.carros << " Casas: " << geracao1.casas << endl;
    cout << "Salario: ";
    geracao1.setsalario(10000);
    cout << geracao1.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao1.setprofissao("Engenheiro\n");
    cout << geracao1.getprofissao();
    //DADOS PAI
cout << "Pai - Caracteristicas" << endl;
    Pai geracao2(40,3,2);
    cout << "Idade: " << geracao2.idade << " Carros: " << geracao2.carros << " Casas: " << geracao2.casas << endl;
    cout << "Salario: ";
    geracao2.setsalario(7000);
    cout << geracao2.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao2.setprofissao("Analista de Sistemas\n");
    cout << geracao2.getprofissao();

    //DADOS FILHO
    cout << "Filho - Caracteristicas" << endl;
    Filho geracao3(23,1,1);
    cout << "Idade: " << geracao3.idade << " Carros: " << geracao3.carros << " Casas: " << geracao3.casas << endl;
    cout << "Salario: ";
    geracao3.setsalario(3000);
    cout << geracao3.getsalario();
    cout <<"\n";
    cout << "Profissao: ";
    geracao3.setprofissao("Professor");
    cout << geracao3.getprofissao();
    return 0;
}

Resultado


Avo - Caracteristicas
Idade: 65 Carros: 6 Casas: 4
Salario: 10000
Profissao: Engenheiro
Pai - Caracteristicas
Idade: 40 Carros: 3 Casas: 2
Salario: 7000
Profissao: Analista de Sistemas
Filho - Caracteristicas
Idade: 23 Carros: 1 Casas: 1
Salario: 3000
Profissao: Professor
Process returned 0 (0x0)   execution time : 0.030 s
Press any key to continue.

Vou ver o que dá pra avançar nisso.

Muito obrigado a todos.

Qual foi a característica herdada pelos homens da família? Na árvore genealógica.

Postado
2 horas atrás, Mauro Britivaldo disse:

@TomJohn Boa tarde!

Qual foi a característica herdada pelos homens da família? Na árvore genealógica.

Eu resolvi não fazer baseado na árvore genealógica por que a questão não foi específica e também eu queria primeiramente afixar o conteúdo. A partir de agora posso fazer baseado nas características como você citou acima :D

adicionado 1 minuto depois
3 horas atrás, arfneto disse:

:( Acho que não leu o que eu escrevi nem rodou o programa que eu mostrei

Fiz sim!

  • Curtir 1
Postado

Então...

  Veja suas classes: 

//HERANCA (CLASSE DERIVADA)
class Pai: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Pai(int i, int car, int cas):Avo(i, car, cas){

    };
};

class Filho: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Filho(int i, int car, int cas):Avo(i, car, cas){

    };
};

E o exemplo que te mostrei

class Tataravo
{
public:
    string nome;
public:
    Tataravo()    { nome = "bisavo, nome nao informado";    };
    Tataravo(string n)
    {
        nome = n; 
        cout << "Criando tataravo: nome="  << nome << endl;
    };
};    // end class


class Bisavo : public Tataravo
{
public:
    string pai;
public:
    Bisavo(){nome = "bisavo, nome nao informado";};
    Bisavo(string n) : Tataravo(n)
    {
        cout << "  Criando bisavo: nome=" << n << endl;
    };
    void nome_do_pai(string n) {
        pai = n;
        //cout << "nome_do_pai(): pai de [" << nome << "]=[" << n << "]" << endl;
    };
};    // end class

E o que expliquei sobre os construtores e a especialização na derivação de classes? E os construtores? Você continua redeclarando todas as variáveis. Se entendeu o que eu expliquei não entendo porque escreveu assim. Suas classes não estão acrescentando nada e ainda sumindo com o que já tinha.

Avo já tinha casas e carros, aí Pai acrescenta outras casas e carros e Filho acrescenta outras casas e carros. Qual o propósito?

 

Compare com o que eu expliquei: você tem a classe Tataravo. Deriva  Bisavo e acrescenta 

public:
string pai;

void nome_do_pai(string);      // setter para o nome do pai

E a classe Neto

class Neto : public Filho
{
public:
    Neto(){    nome = "neto, nome nao informado";};
    Neto(string nome) : Filho(nome)
    { 
        cout << "          Criando neto: nome=" << nome << endl;
    };
};    // end class

E esse trecho de programa 

    Neto n("Neto");
    n.nome_do_pai(f.nome);
    cout << "pai de " << n.nome << " = " << n.pai << endl;

Que mostra isso

Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto
pai de Neto = Pai do Neto

 

Para o programa que eu postei também...

 

Entenda que ao declarar

Neto n("Neto");

n é um Neto mas também é tudo que veio antes. Ele já tem um nome, porque é um Tataravo e herdou nome. Ele tem um pai porque é também um Bisavo e herdou dessa classe. E tem um método nome_do_pai() que herdou de Bisavo também. Esse é o mecanismo de Herança. Atente para essas 3 linhas de código e a declaração de Neto

 

 

 

Postado
5 horas atrás, arfneto disse:

Então...

  Veja suas classes: 


//HERANCA (CLASSE DERIVADA)
class Pai: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Pai(int i, int car, int cas):Avo(i, car, cas){

    };
};

class Filho: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Filho(int i, int car, int cas):Avo(i, car, cas){

    };
};

E o exemplo que te mostrei


class Tataravo
{
public:
    string nome;
public:
    Tataravo()    { nome = "bisavo, nome nao informado";    };
    Tataravo(string n)
    {
        nome = n; 
        cout << "Criando tataravo: nome="  << nome << endl;
    };
};    // end class


class Bisavo : public Tataravo
{
public:
    string pai;
public:
    Bisavo(){nome = "bisavo, nome nao informado";};
    Bisavo(string n) : Tataravo(n)
    {
        cout << "  Criando bisavo: nome=" << n << endl;
    };
    void nome_do_pai(string n) {
        pai = n;
        //cout << "nome_do_pai(): pai de [" << nome << "]=[" << n << "]" << endl;
    };
};    // end class

E o que expliquei sobre os construtores e a especialização na derivação de classes? E os construtores? Você continua redeclarando todas as variáveis. Se entendeu o que eu expliquei não entendo porque escreveu assim. Suas classes não estão acrescentando nada e ainda sumindo com o que já tinha.

Avo já tinha casas e carros, aí Pai acrescenta outras casas e carros e Filho acrescenta outras casas e carros. Qual o propósito?

 

Compare com o que eu expliquei: você tem a classe Tataravo. Deriva  Bisavo e acrescenta 


public:
string pai;

void nome_do_pai(string);      // setter para o nome do pai

E a classe Neto


class Neto : public Filho
{
public:
    Neto(){    nome = "neto, nome nao informado";};
    Neto(string nome) : Filho(nome)
    { 
        cout << "          Criando neto: nome=" << nome << endl;
    };
};    // end class

E esse trecho de programa 


    Neto n("Neto");
    n.nome_do_pai(f.nome);
    cout << "pai de " << n.nome << " = " << n.pai << endl;

Que mostra isso


Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto
pai de Neto = Pai do Neto

 

Para o programa que eu postei também...

 

Entenda que ao declarar


Neto n("Neto");

n é um Neto mas também é tudo que veio antes. Ele já tem um nome, porque é um Tataravo e herdou nome. Ele tem um pai porque é também um Bisavo e herdou dessa classe. E tem um método nome_do_pai() que herdou de Bisavo também. Esse é o mecanismo de Herança. Atente para essas 3 linhas de código e a declaração de Neto

 

 

 

Okay, então Herança não é tão simples como pensei. Vou reestudar.

Postado
1 hora atrás, TomJohn disse:

Okay, então Herança não é tão simples como pensei. Vou reestudar

Talvez seja mais simples do que você pensou!

Leia o programa que te mostrei. Atente para a execução dos construtores um a um até a classe base. Entenda que os métodos e variáveis vão passando adiante. É uma ideia genial eu acho.

E o conceito chave é especialização não herança, eu acho. A classe derivada tem tudo que a classe base tinha. Pode estender algo, invalidar o que tinha ou redefinir o que tinha.

Postado
Em 02/11/2019 às 20:53, arfneto disse:

Então...

  Veja suas classes: 


//HERANCA (CLASSE DERIVADA)
class Pai: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Pai(int i, int car, int cas):Avo(i, car, cas){

    };
};

class Filho: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Filho(int i, int car, int cas):Avo(i, car, cas){

    };
};

E o exemplo que te mostrei


class Tataravo
{
public:
    string nome;
public:
    Tataravo()    { nome = "bisavo, nome nao informado";    };
    Tataravo(string n)
    {
        nome = n; 
        cout << "Criando tataravo: nome="  << nome << endl;
    };
};    // end class


class Bisavo : public Tataravo
{
public:
    string pai;
public:
    Bisavo(){nome = "bisavo, nome nao informado";};
    Bisavo(string n) : Tataravo(n)
    {
        cout << "  Criando bisavo: nome=" << n << endl;
    };
    void nome_do_pai(string n) {
        pai = n;
        //cout << "nome_do_pai(): pai de [" << nome << "]=[" << n << "]" << endl;
    };
};    // end class

E o que expliquei sobre os construtores e a especialização na derivação de classes? E os construtores? Você continua redeclarando todas as variáveis. Se entendeu o que eu expliquei não entendo porque escreveu assim. Suas classes não estão acrescentando nada e ainda sumindo com o que já tinha.

Avo já tinha casas e carros, aí Pai acrescenta outras casas e carros e Filho acrescenta outras casas e carros. Qual o propósito?

 

Compare com o que eu expliquei: você tem a classe Tataravo. Deriva  Bisavo e acrescenta 


public:
string pai;

void nome_do_pai(string);      // setter para o nome do pai

E a classe Neto


class Neto : public Filho
{
public:
    Neto(){    nome = "neto, nome nao informado";};
    Neto(string nome) : Filho(nome)
    { 
        cout << "          Criando neto: nome=" << nome << endl;
    };
};    // end class

E esse trecho de programa 


    Neto n("Neto");
    n.nome_do_pai(f.nome);
    cout << "pai de " << n.nome << " = " << n.pai << endl;

Que mostra isso


Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto
pai de Neto = Pai do Neto

 

Para o programa que eu postei também...

 

Entenda que ao declarar


Neto n("Neto");

n é um Neto mas também é tudo que veio antes. Ele já tem um nome, porque é um Tataravo e herdou nome. Ele tem um pai porque é também um Bisavo e herdou dessa classe. E tem um método nome_do_pai() que herdou de Bisavo também. Esse é o mecanismo de Herança. Atente para essas 3 linhas de código e a declaração de Neto

 

 

 

iniciante na área de novo :D

A intenção não seria no caso discutir sobre árvore genealógica ou qualquer coisa do tipo. Seria somente aprender sobre como aplicar a herança e interagir com ela. O que fiz você disse que foi apenas "redeclarar" as variáveis. O que não to sacando de herança é que o sentido disso não seria herdar as características como o Mauro citou acima? Digamos que o que tentei fazer seja um programa :D ...eu queria ver se "herava" os dados do avô, tipo assim nesse trecho:

 

class Avo{
public:
    int idade, carros, casas;
//CONSTRUTOR
public:
    Avo(int i, int car, int cas){
    idade = i;
    carros = car;
    casas = cas;
    };
    /*DESTRUTOR
    ~Avo(){
        cout << "Vazio" << endl;
    }
    */
//SETTERS AND GETTERS
    void setsalario(int s){
        salario = s;
    }
    int getsalario(){
        return salario;
    }
    void setprofissao(string p){
        profissao = p;
    }
    string getprofissao(){
        return profissao;
    }

Herdar não seria aplicar aqui por exemplo

 

class Pai: public Avo{
public:
    int Idade, Carros, Casas;
public:
    Pai(int i, int car, int cas):Avo(i, car, cas){

    };
};

E ter como resultado a representação dos mesmos dados do Avô?

Resultado

 

Avo - Caracteristicas
Idade: 65 Carros: 6 Casas: 4
Salario: 10000
Profissao: Engenheiro

Pai - Caracteristicas
Idade: 40 Carros: 3 Casas: 2
Salario: 7000
Profissao: Analista de Sistemas

Filho - Caracteristicas
Idade: 23 Carros: 1 Casas: 1
Salario: 3000
Profissao: Professor

E eu rodei o seu programa e entendi ele sim. Apenas o que fiz não é herança? Eu aprendi a fazer daquela forma a partir de sites como w3schools, geeksforgeeks etc...

Postado
23 minutos atrás, TomJohn disse:

E eu rodei o seu programa e entendi ele sim. Apenas o que fiz não é herança? Eu aprendi a fazer daquela forma a partir de sites como w3schools, geeksforgeeks

 

Pois é: o programa que eu te mostrei mostra o que é herdado e eu até expliquei de novo. E também expliquei o que seu programa não fez. 

Espero que esse sites não tenham dito nada diferente porque eles estariam errados.

Entenda que como eu disse antes, herança é melhor vista como especialização de classes. As coisas funcionam até como você imaginava, até o momento em que você declara novas variáveis nas subclasses com os mesmos nomes que nas classes base. E como você redeclarou todas não herdou nada na prática.

 

Atente para o programa que te mostrei: Tataravo é a única classe que tem nome no meu exemplo. E o Bisavô é a única que tem pai e acrescenta o método nome_do_pai(), que foi herdado por todas subclasses e inclusive usado no meu exemplo, por uma variável da classe Neto...

 

Quando você redeclara uma variável dessas ocorre o que na literatura se chama de shadowing eu creio, e as variáveis com os mesmos nomes nas classes base ficam como fora de escopo.

 

Entenda que um Neto é também um Tataravo, e um Pai e tudo que tem no caminho....

 

Postado
Em 02/11/2019 às 21:56, TomJohn disse:

Okay, então Herança não é tão simples como pensei. Vou reestudar.

Não gosto de C++, mas lembrava que era mais simples também.

Eu teria respondido desta maneira ...

#include <iostream>
class Caracteristica {
public:
        bool cmagro;
        bool calto;
        bool cclaro;
        bool cdentuco;
        bool cmaozada;
        bool ccalvo;
        Caracteristica (){};
};
class Trisavo: public Caracteristica {
public: Trisavo (){ this->cmagro = true; }
};
class Bisavo: public Trisavo {
public: Bisavo (){ this->calto = true; };
};
class Avo: public Trisavo {
public: Avo (){ this->cclaro = true; };
};
class Pai: public Trisavo {
public: Pai (){ this->cdentuco = true; };
};
class Filho: public Trisavo {
public: Filho (){ this->cmaozada = true; };
};
class Neto: public Trisavo {
public: Neto (){ this->ccalvo = true; };
};
int main(void)
{
        Trisavo t;
        Bisavo  b;
        Avo     v;
        Pai     p;
        Filho   f;
        Neto    n;

        std::cout <<("Se todos sao magros a culpa e do ...")<< std::endl;
        if ((t.cmagro == b.cmagro)
                      &&(t.cmagro == v.cmagro)
                      &&(t.cmagro == p.cmagro)
                      &&(t.cmagro == f.cmagro)
                      &&(t.cmagro == n.cmagro)){
                std::cout <<("Tataravo!")<< std::endl;
        }
        else
                std::cout <<("desconhecido rsrsrs!")<< std::endl;
        return 0;
}

 

Postado

@Mauro BritivaldoHahaha ótimo. você usou this pointer. Legal. Tinha visto assim pelo CFB Cursos. Eu acreditava que bastava colocar ":" e tava herado. Mas existem diversas maneiras de fazer. Guardarei ambas. Venho em breve com mais dúvidas. Valeu!!!

  • Curtir 1
Postado
5 horas atrás, TomJohn disse:

Tinha visto assim pelo CFB Cursos. Eu acreditava que bastava colocar ":" e tava herado

 

Sim. Basta isso. Só que é a única maneira. Na declaração da classe declare a classe base.

5 horas atrás, TomJohn disse:

Mas existem diversas maneiras de fazer. Guardarei ambas

 

Não. Não existem. E se existir não é essa por certo.

 

@Mauro Britivaldo e @TomJohn espero que tenham paciência em ler o que vou escrever , incluindo os exemplos. Estou com tempo hoje e acho que essa é uma dúvida comum e esse é o propósito do forum afinal

 

Atenção para o exemplo acima: não é assim que funciona. 

 

Citação

Se você excluir o this-> desse programa aí acima vai dar exatamente na mesma. 

 

this simplesmente contem o endereço do objeto que contém a variável ou método. 

 

É especialmente importante para eliminar ambiguidades quando um método ou variável é redefinido, como você havia feito, @TomJohn, em todas as classes do seu exemplo. Nesse programa que @Mauro Britivaldo escreveu não há qualquer redefinição e os valores são herdados da (nova) classe base Caracteristica. Todos. E não há qualquer ambiguidade. Nesse caso as classes não são herdadas como provavelmente o enunciado esperava, nível após nível, mas apenas a partir de uma classe Tataravo que por sua vez tem uma nova classe base.

 

Repito: this nesse exemplo acima é totalmente inócuo. Apague e verão. Só existe uma variável de cada atributo, boolean. E como C++ vai chamar todos os construtores até a classe base os atributos estarão atribuídos na ordem de construção.

 

Vou mostrar mais uma vez um exemplo disso, com a saída para tentar de novo explicar isso.

 

É um conceito essencial para entender essa e outras linguagens orientadas a objeto, como java.

 

Considerem o exemplo das classes derivadas a partir de Tataravo até o Neto. Vamos usar uma variável geração, que numera a geração a partir do Tataravo = 1 até o Neto = 6 então.

 

Como eu expliquei mais de uma vez, e vocês viram no exemplo inicial, ao redefinir uma variável com o mesmo nome a cada subclasse gerada, desaparece a variável ou método da classe acima. Como temos 5 gerações acima do Neto, todas elas desaparecem, como desapareceram os carros e casas em seu programa,  @TomJohn

 

Não desapareceram, não sei como ensinam isso em português, mas ficam ofuscadas ou sombreadas. shadowing é a expressão comum na documentação.

 

Mas como a cada derivação é construída uma classe desde a classe base, e eu mostrei isso pra vocês, as outras gerações ainda estão lá. Apenas não se pode vê-las.

 

EXEMPLO

 

Considerando as classes do exemplo anterior, apenas acrescentei uma variável 

    int geração;

e no construtor da classe numerei as gerações a partir do Tataravo

Tataravo    geração 1
Bisavo      geração 2
Avo         geração 3
Pai         geração 4
Filho       geração 5
Neto        geração 6

E vou explicar como acessar essas gerações todas --- desculpem o trocadilho :D 

 

Para explicar a necessidade real de this, vou acrescentar uma ambiguidade real criando um novo construtor para Neto, que permite passar uma geração como parametro, e usando o MESMO nome, geração.


As outras variáveis com o mesmo nome, que nesse caso existem mesmo, não geram ambiguidade: isso foi idealizado assim pelos construtores dessas linguagens. Herança tem a ver com especialização e quando você cria um método ou variável com o mesmo nome se imagina que você fez isso DE PROPÓSITO. Em java se usa até uma anotação @override na frente de um método para indicar que você sabe o que está fazendo e não se enganou apenas. Não gera ambiguidade porque redefine o método ou valor.

 

Eis a classe Neto, que deriva de Pai que deriva de Avo... e tal

class Neto : public Filho
{
public:
    int        geração;

public:
    Neto() { nome = "neto, nome nao informado"; };
    // construtor com nome
    Neto(string nome) : Filho(nome)
    {
        cout << "          Criando neto: nome=" << nome << endl;
        geração = 6;
    };
    // construtor com nome e geração
	Neto(string nome, int geração) : Filho(nome)
	{
		cout << "          Criando neto: nome=" << nome << " geração=" << geração << endl;
		cout << "geração, o parametro=" << geração << endl;
		Tataravo* tataravo = this;
		geração = tataravo->geração;
		cout << "Todo Tataravo tem geração=1 definida no construtor da classe" << endl;
		cout << "geração, o parametro copiado do tataravo dessa instancia=" << geração << endl;
		this->geração = geração;
		cout << "geração, na classe=" << this->geração << endl;
	};

};    // end class

E considerem esse programa

    cout << "\n----- Criando Neto (usando a geração)" << endl;
    Neto n("Neto", 2000);
    n.nome_do_pai("Pai do Neto");
    cout << "Em main() a geração do Neto ='" << n.geração << "'" << endl;

    cout << "\n----- Criando Neto so com o nome" << endl;
    Neto outro("Outro Neto");
    outro.nome_do_pai("Pai do Outro Neto");
    cout << "Em main() a geração do Outro Neto ='" << outro.geração << "'" << endl;

Ao declarar dois Neto usando os diferentes construtores acho que vão entender quando e porque se usa this e, ao mesmo tempo, como usar o próprio endereço do objeto --- this --- para ressuscitar a geração do Tataravô que tinha sumido ao ser redefinida pelas classes derivadas.

 

Atentem para o trecho

        Tataravo* tataravo = this;
        geração = tataravo->geração;
        cout << "Todo Tataravo tem geração=1 definida no construtor da classe" << endl;
        cout << "geração, o parametro copiado do tataravo dessa instancia=" << geração << endl;
        this->geração = geração;

no construtor, e para o RESULTADO do PROGRAMA

----- Criando Neto (usando a geração)
Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto geração=2000
geração, o parametro=2000
Todo Tataravo tem geração=1 definida no construtor da classe
geração, o parametro copiado do tataravo dessa instancia=1
geração, na classe=1
Em main() a geração do Neto ='1'

----- Criando Neto so com o nome
Criando tataravo: nome=Outro Neto
  Criando bisavo: nome=Outro Neto
    Criando avo: nome=Outro Neto
      Criando pai: nome=Outro Neto
        Criando filho: nome=Outro Neto
          Criando neto: nome=Outro Neto
Em main() a geração do Outro Neto ='6'

Vejam que no primeiro caso o que ficou valendo para a geração foi o valor que estava oculto na classe base 


Como acessar os valores ofuscados nas classes base então? Assim

int main()
{
    cout << "\n----- Criando Neto" << endl;
    Neto n("Neto");
    n.nome_do_pai("Pai do Neto");

    cout << "pai de " << n.nome << " = " << n.pai << endl;
    cout << "\nUsando a mesma variavel, da classe '" << typeid(n).name() << "'" << endl;
    cout << "Neto: " <<        n.geração << endl;
    cout << "Filho: " <<    ((Filho)(n)).geração << endl;
    cout << "Pai: " <<        ((Pai)(n)).geração << endl;
    cout << "Avo: " <<        ((Avo)(n)).geração << endl;
    cout << "Bisavo: " <<   ((Bisavo)(n)).geração << endl;
    cout << "Tataravo: " << ((Tataravo)(n)).geração << endl;
}    // end main()

Que mostra os desaparecidos e você pode testar em seu exemplo inicial, @TomJohn

 

Notem que typeid(n).name() mostra o valor da classe da variável n e vai mostrar class Neto como esperado. Isso é um comando do C++

----- Criando Neto
Criando tataravo: nome=Neto
  Criando bisavo: nome=Neto
    Criando avo: nome=Neto
      Criando pai: nome=Neto
        Criando filho: nome=Neto
          Criando neto: nome=Neto
pai de Neto = Pai do Neto

Usando a mesma variavel, da classe 'class Neto'
Neto: 6
Filho: 5
Pai: 4
Avo: 3
Bisavo: 2
Tataravo: 1

Entendam: tudo isso está contido --- encapsulado --- dentro da mesma variável n, do tipo Neto, mas que também é um Pai, Avo e tal.... Todos os valores de casas e carros por exemplo, para todas as classes intermediárias, @TomJohn podem ser acessados assim.

 

Citação

((Bisavo)(n)).geração

 

é o que se chama cast e permite recuperar então esses valores, mostrando o valor de geração ao ver n como um Bisavo, que tem geração = 2.

Citação

 

Estou escrevendo isso apenas para mostrar como funciona. Recomendo usar muito fugir disso que chamei de "artifícios" num post anterior. C++ é uma linguagem enorme e  Herança é um conceito sensacional. Mas tem efeitos colaterais. Estender uma classe tem a ver com especialização e permite escrever programas muito rápidos, compactos e poderosos ao usar o conceito a favor . . . Mas pode ser um pesadelo. Abusar de casts ou converter ponteiros pode ser outro desastre. 

 

 

  • Curtir 1
Postado
Em 05/11/2019 às 20:45, TomJohn disse:

Eu acreditava que bastava colocar ":" e tava herado

@TomJohn Sim, basta colocar que está herdado. Herda é exatamente isso; passar membros entre classes também! A palavra chave this indica e permite dizer: estes sãos os meus membros.

 

 

@arfneto Concordo apenas com relação a palavra chave. Usei na qualidade de bom indicacador que esta classe tem membros explicitamente. Acredito que ...

Em 05/11/2019 às 20:45, TomJohn disse:

Tinha visto assim pelo CFB Cursos

por no mínimo esse mesmo motivo.

 

Sim eu li tua postagem, muito bem explicada e cheia de detalhes prestimosíssimos, ainda sim para mim é um monologo porque eu não consigo entender e obrigado!

 

 

 


 

Enunciado

Citação

Problema 17:

Desenvolva um programa em C++ baseado em uma árvore genealógica.

O programa deve conter  a classe Tataravô e as seguintes subclasses Bisavô, Avô, Pai, Filho e Neto devem herdar as características de Tataravô.

 

Esquema

Trisavô (Magro) ... ↳   Neto (Calvo)

O Neto é magro e Calvo ... O Trisavô é magro.

 

Código

class Trisavo: public Caracteristicas {
public: Trisavo (bool cmagro = true){ this->cmagro = cmagro; }
};

...

class Neto: public Trisavo {
public: Neto (bool ccalvo = true){ this->ccalvo = ccalvo; };
};

***

Postado
12 horas atrás, Mauro Britivaldo disse:

A palavra chave this indica e permite dizer que estes sãos os meus membros.

 

Não, ela não indica nada disso. this é apenas um ponteiro para o objeto em que o método é chamado ou a variável da classe é usada. E é incluído automaticamente se não for colocado. Não é a minha opinião. Só é assim.

 

Veja a documentação. Por exemplo aqui

 

Eu mostrei os dois possíveis usos de this com um exemplo ao criar o construtor que usava um parâmetro com o mesmo nome de uma variável membro. E mostrei como usar this para usar --- claro --- o endereço da classe para criar um ponteiro para uma classe base e recuperar o valor de uma variável que havia sido ocultada: 

    Neto(string nome, int geração) : Filho(nome)
    {
        cout << "          Criando neto: nome=" << nome << " geração=" << geração << endl;
        cout << "geração, o parametro=" << geração << endl;
        Tataravo* tataravo = this;
        geração = tataravo->geração;
        cout << "Todo Tataravo tem geração=1 definida no construtor da classe" << endl;
        cout << "geração, o parametro copiado do tataravo dessa instancia=" << geração << endl;
        this->geração = geração;
        cout << "geração, na classe=" << this->geração << endl;
    };

Esses são os dois usos:

  • Eliminar a ambiguidade em relação ao parâmetro geração
  • pegar o endereço do objeto para converter o ponteiro e acessar variáveis na classe Tataravo

No seu caso como eu disse esse parâmetro nada acrescenta.

 

Não conheço esse CFB cursos mas se acaso disseram algo distinto do que eu disse está errado. Só isso. Basta ver a documentação. Repito, não estou dando uma opinião. É assim há mais de 30 anos.

 

E eu mostrei um exemplo e o resultado.

 

13 horas atrás, Mauro Britivaldo disse:

Sim eu li tua postagem, muito bem explicada e cheia de detalhes prestimosíssimos, ainda sim para mim é um monologo porque eu não consigo entender

 

Eu não sei o que faltou. Talvez pudesse fazer uma pergunta específica e quem sabe eu possa escrever de outro modo

 

O conceito realmente importante é o que está nessas linhas

    cout << "Neto: " <<        n.geração << endl;
    cout << "Filho: " <<    ((Filho)(n)).geração << endl;
    cout << "Pai: " <<        ((Pai)(n)).geração << endl;
    cout << "Avo: " <<        ((Avo)(n)).geração << endl;
    cout << "Bisavo: " <<   ((Bisavo)(n)).geração << endl;
    cout << "Tataravo: " << ((Tataravo)(n)).geração << endl;

E a recomendação é a que está no fim: fuja disso e só use quando for o desejo redefinir um método ou propriedade.

 

Postei o programa de teste. Eu tinha me esquecido

 

 

programa-cpp.txt

Postado
1 hora atrás, arfneto disse:

Não, ela não indica nada [...]

Discordo, this tem esse significado sim, a palavra chave indica os membros desta classe.

 
1 hora atrás, arfneto disse:

Não conheço esse CFB cursos mas se acaso disseram algo distinto do que eu disse está errado

É por aí.

 
1 hora atrás, arfneto disse:

Eu não sei o que faltou. Talvez pudesse fazer uma pergunta específica e quem sabe eu possa escrever de outro modo

Obrigado!

Postado

@arfneto 😢

Isso eu vou ter de reler e reler. É muita informação e digamos que é um conteúdo que TEM de ser de fácil assimilação em comparação ao que me espera no futuro com C++. Já preparava um outro exemplo para ver se entendi, mas vou rever desde o primeiro post se consigo aplicar tudo que foi ensinado aqui.

Muitíssimo agradecido pela esclarecedora resposta.

 

Ah, e relendo as respostas você perguntou sobre multilevel Inheritance.

Seria algo assim Aqui

Postado
Em 01/11/2019 às 14:05, arfneto disse:

herança múltipla seria o caso de uma classe ser derivada de mais de uma outra

 

Multilevel eu não sei o que é, talvez você pudesse dar uma referência de onde leu isso

 

Sim!

Entendi. Eu não imaginava que alguém fosse dar um nome para uma coisa assim tão besta. Uma classe derivar de uma classe que deriva de outra não é nada de especial, e vem da simples necessidade às vezes. Imagine por exemplo estender --- herdar --- de uma classe botão, numa interface gráfica. Você pode estender a classe para declarar um método que cria uma animação com uma imagem no fundo do botão. E aí um dia você resolve criar uma classe que herda esse botão animado e cria uma família deles onde a mesma imagem vai passado de um pro outro e tem um efeito de uma barra de progresso com uma barra vertical ao fundo. Pronto: MultiLevel. 

 

Siga o exemplo que mostrei e atende para para o "artifício" para acessar as variáveis sumidas nas classes bases. Atente para o lance da variavel geração que mostra bem o que está acontecendo. Atende para o uso de this para resolver a ambiguidade naquele último construtor. Implemente aquilo no seu programa para recuperar as idades e casas das classes anteriores e vai entender esse aspecto de herança.

 

Esse exemplo que discutimos é uma Herança MultiLevel com 6 níveis :) bobagem. Mas era isso que o enunciado queria mostrar.

 

Eu imaginei num primeiro momento  que você falava de herança múltipla, que é realmente um conceito avançado e chato em que uma classe é derivada de mais de uma classe. Nunca tinha ouvido falar em herança multilevel porque afinal é uma coisa banal. Apenas mais um nível de construtores a chamar e você define tantos níveis quanto precisa.Enquanto precisa. Se precisa.

 

Note que escrever esse simples programa em C por exemplo seria o diabo. E sem garantias que o C++ dá.

 

Boa sorte com C++. Penso que vai achar a linguagem poderosa e cheia de truques. E os programas em C++ rodam muito muito rápido. Quase tanto quanto os programas C.

 

Se tiver paciência, recomendo muito rodar aquele programa que postei e inserir aqueles conceitos no seu programa original.

adicionado 7 minutos depois

Acho que muitos autores vão recomendar a mesma coisa sobre aprender C++: entender aritmética de ponteiros, alocação de memória  e conceitos básicos de programação. Aí entender herança, polimorfismo e encapsulamento. Usar templates e usar algumas classes da STL. Programar algumas estruturas de dados pode ajudar muito a entender tudo, em especial aquelas que já tem equivalente na biblioteca padrão, como vetores e listas e mapas, porque aí pode testar suas soluções com as providas pelo C++.

 

Se programava em C --- ou Pascal ou FORTRAN --- reescrever seus programas antigos em C++ pode ser muito legal também. Se usava R ou Python pode ser legal ver seus programas rodarem umas 20 vezes mais rápido também.

 

Se programava em java vai se sentir em casa, por outro lado. Só que com os programas rodando bem mais rápido.

 

Postado
6 horas atrás, arfneto disse:

Eu imaginei num primeiro momento  que você falava de herança múltipla, que é realmente um conceito avançado e chato em que uma classe é derivada de mais de uma classe. Nunca tinha ouvido falar em herança multilevel porque afinal é uma coisa banal. Apenas mais um nível de construtores a chamar e você define tantos níveis quanto precisa.Enquanto precisa. Se precisa.

Eu não vi nenhuma questão por falta de tempo mas depois eu pensei em fazer o seguinte: duas classes, uma chamada Pai e outra chamada Mãe. Pai por exemplo teria como características, cabelos pretos, olhos marrons, magro, alto etc e mãe loira, gorda, baixa, olhos verdes etc...Daí 4 filhos e calcular a porcentagem de herdarem as características de ambos. Isso seria herança múltipla?

 

6 horas atrás, arfneto disse:

Se tiver paciência, recomendo muito rodar aquele programa que postei e inserir aqueles conceitos no seu programa original.

Isso vou fazer com certeza, só resolver o probleminha com pc porque divido o que tenho...não importa.

Eu nunca programei em nenhuma linguagem, mas pretendo no futuro estudar Assembly. No momento tentando mexer com C++, C# e PHP.

Postado
5 horas atrás, TomJohn disse:

Eu não vi nenhuma questão por falta de tempo mas depois eu pensei em fazer o seguinte: duas classes, uma chamada Pai e outra chamada Mãe. Pai por exemplo teria como características, cabelos pretos, olhos marrons, magro, alto etc e mãe loira, gorda, baixa, olhos verdes etc...Daí 4 filhos e calcular a porcentagem de herdarem as características de ambos. Isso seria herança múltipla?

 

  • Vai depender de como declarar. Recomendo esquecer isso por enquanto e se concentrar em entender o que eu expliquei sobre herança
  • rodar aquele exemplo
  • implementar o que eu mostrei lá naquele programa em seu programa original para pegar os valores sumidos de carros e casas das classes bases.

Se fizer isso vai ter uma ideia precisa do conceito.

 

Herança Múltipla é isso:

class Coisas : Bola, Quadrado, Triangulo
{
public:
    Coisas()
    {
        cout << "criando um Container" << endl;
    }

    ~Coisas()
    {
        cout << "destruindo um Container" << endl;
    }

};


Onde a classe Coisas herda --- estende --- as classes Bola, Quadrado e Triangulo

 

Veja o resultado

criando uma Bola
criando uma Quadrado
criando uma Triangulo
criando uma Coisa
destruindo uma Coisa
la se vai uma Triangulo
la se vai uma Quadrado
la se vai uma Bola

Deste programa enorme

int main()
{
	Coisas		uma_coisa;
	return 0;
}	// end main()

O programa todo

#pragma once
#include <iostream>
#include <typeinfo>

using namespace std;

class Bola
{
public:
	Bola();
	~Bola();
};
Bola::Bola(){	cout << "criando uma Bola" << endl;}
Bola::~Bola(){	cout << "la se vai uma Bola" << endl;}


class Quadrado
{
public:
	Quadrado();
	~Quadrado();
};
Quadrado::Quadrado(){	cout << "criando uma Quadrado" << endl;}
Quadrado::~Quadrado(){	cout << "la se vai uma Quadrado" << endl;}

class Triangulo
{
public:
	Triangulo();
	~Triangulo();
};

Triangulo::Triangulo(){	cout << "criando uma Triangulo" << endl;}
Triangulo::~Triangulo(){	cout << "la se vai uma Triangulo" << endl;}

class Coisas : Bola, Quadrado, Triangulo
{
public:
	Coisas()	{		cout << "criando uma Coisa" << endl;	}
	~Coisas()	{		cout << "destruindo uma Coisa" << endl;	}
};


int main()
{
	Coisas		uma_coisa;
	return 0;
}	// end main()

 

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...