Ir ao conteúdo
  • Cadastre-se

C++ fazer instanceof em C++


Ir à solução Resolvido por arfneto,

Posts recomendados

Estou escrevendo uma classe base(Animal) que contem 4 filhos, desejo instanciar essas classes e armazena-las em algum container, para posteriormente abri-lo e diferenciar cada classe que foi armazenada nele. Sei que em Java existe o operador instanceof para comparar cada objeto com uma possível classe.

 

Andei pesquisando, e achei 2 soluções (a primeira me pareceu mais elegante) elas funcionam muito bem quando eu passo um objeto pra elas, mas não quando trabalho com containers. Segue o código

 

animal.h


#ifndef ANIMAL_H
#define ANIMAL_H

#include <string>

using namespace std;

class Animal{

protected:
    string nome;
    char sexo; // M|F
    int idade;
    float peso;
    bool outraFamilia; //true = se não for nenhumas das classes filhos
public:
    Animal(string nome, char sexo, int idade, float peso, bool outraFamilia);

    string getNome();
    char getSexo();
    int getIdade();
    float getPeso();
    bool isOutraFamilia();
    //~Animal();
};

class Cachorro : public Animal{
private:
    string raca;
    string pelagem;
    bool adestrado;
    bool castrado;
public:
    Cachorro(string raca, string pelagem, bool adestrado, bool castrado, string nome, char sexo, int idade, float peso, bool outraFamilia);
    string getRaca();
};

class Gato : public Animal{
private:
    string pelagem;
    bool castrado;
    string observacao;
public:
    Gato(string pelo, bool castrado, string observacao, string nome, char sexo, int idade, float peso, bool outraFamilia);
    string getPelagem();
};

class Ave : public Animal{
private:
    bool dieta;
    bool gaiola;
    string penugem;
    string especie;
    float invergadura;
public:
    Ave(bool dieta, bool gaiola, string penugem, string especie, float invergadura, string nome, char sexo, int idade, float peso, bool outraFamilia);
    bool isDieta();
    string getEspecie();
};

class Tartaruga : public Animal{
private:
    bool dieta;
    string tipoDeAmbiente;
    float tamanhoDaCarapaca;
public:
    Tartaruga(bool dieta, string tipoDeAmbiente, float tamanhoDaCarapaca, string nome, char sexo, int idade, float peso, bool outraFamilia);
    bool isDieta();
    string getTipoDeAmbiente();
    float getTamanhoDaCarapaca();
};


#endif // ANIMAL_H

 

 

animal.cpp


#include "animal.h"

using namespace std;

Animal::Animal(string nome, char sexo, int idade, float peso, bool outraFamilia){
    this->nome = nome;
    this->sexo = sexo;
    this->idade = idade;
    this->peso = peso;
    this->outraFamilia = outraFamilia;
}

string Animal::getNome(){
    return this->nome;
}

char Animal::getSexo(){
    return this->sexo;
}

int Animal::getIdade(){
    return this->idade;
}

float Animal::getPeso(){
    return this->peso;
}

bool Animal::isOutraFamilia(){
    return this->outraFamilia;
}


Cachorro::Cachorro(string raca, string pelagem, bool adestrado, bool castrado, string nome, char sexo, int idade, float peso, bool outraFamilia):Animal(nome, idade, sexo, peso, outraFamilia){
    this->raca = raca;
    this->pelagem = pelagem;
    this->adestrado = adestrado;
    this->castrado = castrado;
}

string Cachorro::getRaca(){
    return this->raca;
}

Gato::Gato(string pelagem, bool castrado, string observacao, string nome, char sexo, int idade, float peso, bool outraFamilia):Animal(nome, idade, sexo, peso, outraFamilia){
    this->pelagem = pelagem;
    this->castrado = castrado;
    this->observacao = observacao;
}

string Gato::getPelagem(){
    return this->pelagem;
}

Ave::Ave(bool dieta, bool gaiola, string penugem, string especie, float invergadura, string nome, char sexo, int idade, float peso, bool outraFamilia):Animal(nome, sexo, idade, peso, outraFamilia){
    this->dieta = dieta;
    this->gaiola = gaiola;
    this->penugem = penugem;
    this->especie = especie;
    this->invergadura = invergadura;
}

bool Ave::isDieta(){
    return this->dieta;
}
string Ave::getEspecie(){
    return this->especie;
}

Tartaruga::Tartaruga(bool dieta, string tipoDeAmbiente, float tamanhoDaCarapaca, string nome, char sexo, int idade, float peso, bool outraFamilia) : Animal(nome, sexo, idade, peso, outraFamilia){
    this->dieta = dieta;
    this->tipoDeAmbiente = tipoDeAmbiente;
    this->tamanhoDaCarapaca = tamanhoDaCarapaca;
}

bool Tartaruga::isDieta(){
    return this->dieta;
}

string Tartaruga::getTipoDeAmbiente(){
    return tipoDeAmbiente;
}

float Tartaruga::getTamanhoDaCarapaca(){
    return this->tamanhoDaCarapaca;
}








 

 

main.cpp

#include <sstream>
#include "animal.h"
#include <vector>
#include <iostream>

using namespace std;

template<typename Base, typename T>

inline bool instanceof(const T*) {
   return is_base_of<Base, T>::value;
}

int main(int argc, char *argv[]){

    Animal *bicho1 = new Gato("branco", true, "", "Bituca", 'M', 0, 0.5, false);
    cout << bicho1->getNome() << endl;

    Animal *bicho2 = new Cachorro("PitBull", "marrom", true, false, "Naja", 'F', 5, 15.4, false);
    cout << bicho2->getNome() << endl;

    Animal *bicho3 = new Ave(false, false, "azul", "araris", 23.3, "Azulinha", 'F', 1, 0.3, false);
    cout << bicho3->getNome() << endl;

    cout << endl;

    vector <Animal*> *listaDeAnimais = new vector<Animal*>;
    listaDeAnimais->push_back(bicho1);
    listaDeAnimais->push_back(bicho2);
    listaDeAnimais->push_back(bicho3);
  
//****************************** MANEIRA 1 **********************************
    for(int i = 0; i < listaDeAnimais->size(); i++){
        if(instanceof<Ave>(listaDeAnimais->at(i)))
            cout << listaDeAnimais->at(i)->getNome() << " EH UMA AVE" << endl;
         else
            if(instanceof<Cachorro>(listaDeAnimais->at(i)))
                cout << listaDeAnimais->at(i)->getNome() << " EH UM CACHORRO" << endl;
             else
                if(instanceof<Gato>(listaDeAnimais->at(i)))
                    cout << listaDeAnimais->at(i)->getNome() << " EH UM GATO" << endl;
                 else
                    if(instanceof<Tartaruga>(listaDeAnimais->at(i)))
                        cout << listaDeAnimais->at(i)->getNome() << " EH UM TARTARUGA" << endl;
                     else
                        cout << listaDeAnimais->at(i)->getNome() << " EH OUTRO ANIMAL" << endl;

    }

    cout << endl;

//****************************** MANEIRA 2 **********************************
    for(int i = 0; i < listaDeAnimais->size(); i++){
       if(static_cast<Ave*>(listaDeAnimais->at(i)) != nullptr){
           cout << listaDeAnimais->at(i)->getNome() << " EH UMA AVE" << endl;
       } else
           if(static_cast<Cachorro*>(listaDeAnimais->at(i)) != nullptr){
               cout << listaDeAnimais->at(i)->getNome() << " EH UM CACHORRO" << endl;
           } else
               if(static_cast<Gato*>(listaDeAnimais->at(i)) != nullptr){
                   cout << listaDeAnimais->at(i)->getNome() << " EH UM GATO" << endl;
               } else
                   if(static_cast<Tartaruga*>(listaDeAnimais->at(i)) != nullptr){
                       cout << listaDeAnimais->at(i)->getNome() << " EH UM TARTARUGA" << endl;
                   } else
                       cout << listaDeAnimais->at(i)->getNome() << " EH OUTRO ANIMAL" << endl;

    }


    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

11 horas atrás, Gabriel Barbosa Brandao disse:

desejo instanciar essas classes e armazena-las em algum container, para posteriormente abri-lo e diferenciar cada classe que foi armazenada nele. Sei que em Java existe o operador instanceof para comparar cada objeto com uma possível classe

 

Se entendi seu exemplo quer usar um container de ponteiros para uma classe base e depois acessar métodos e propriedades das classes derivadas usando os tais ponteiros, e parece uma necessidade razoável.

 

java tem instanceof(), Python tem isinstance(). Mas C++ é um Animal bem diferente ;) . Em Python uma declaração é só a presença do nome. Você escreve lá um nome e pronto. E assim é muito mais comum você precisar saber que d1@b0 é um nome lá. java ;) não tem ponteiros e alocação dinâmica. Em Python muitas coisas são imutáveis. java não tem herança múltipla. É tudo mais simples. Ou mais complicado. Depende de onde olhar. 

 

De volta ao seu programa
 

class Animal
{
protected:
    string nome;
    char   sexo; // M|F
    int    idade;
    float  peso;
    bool   outraFamilia; //true = se não for nenhumas das classes filhos
    Animal(string nome, char sexo, int idade, float peso, bool outraFamilia);

public:
    virtual string getNome();
    char getSexo();
    int getIdade();
    float getPeso();
    bool isOutraFamilia();
};

 

Não sei se está escrevendo isso para uso próprio, mas a simples presença de outraFamilia na classe é sinal de que algo está errado. Usando orientação a objetos precisou de uma variável bool para indicar se é uma instância da classe base e isso contradiz a própria filosofia.
 

Se tem um bool porque então não usar um
 

    int tipoDeAnimal;


e resolver tudo? O espaço vai ser o mesmo. O tempo vai ser o mesmo. E tudo fica mais simples. E muito mais rápido se não usar uma classe polimórfica.

 

Um container de ponteiros em C++


O que quer fazer tem sentido, mas alocar dinamicamente um container nem tanto.  Um dos parâmetros para o construtor de vector por exemplo é o próprio alocador. Quando você declara um ponteiro para uma classe que tem um parâmetro no próprio construtor que é o alocador em geral tem algo errado ;)  E vector implementa move semantics então performance em geral é excelente. No caso de nós não-desenvolvedores da STL talvez a gente nunca chegue perto do que esses caras conseguem escrever. 

Você sequer liberou a memória alocada ainda.

 

O prof. Stroustrup, criador de C++ há 40 anos atrás, sempre diz com orgulho que o overhead de declarar um vetor é mínimo em relação a um array. E está usando um vetor. Qual a vantagem de alocar um ponteiro em main() se vetor  tem move semantics por exemplo, e libera memória sozinho? 

 

typeid e decltype 


Talvez entender esses comandos também ajude conforme for implementando seu programa.

 

Ao invés de declarar
 

      vector <Animal*> *listaDeAnimais = new vector<Animal*>;

 

Prefira sempre
 

    unique_ptr< vector<Animal*> > zoo(new vector<Animal*>);

 

Quase nunca há razão para usar new e delete e é recomendado evitar a todo custo há mais de uma década. Note que você nem liberou a memória em seu programa.

 

E nesse caso prefira o simples
 

    vector<Animal*> zoo{};

 

A classe Animal


Já te disse isso antes sobre esse programa: Animal deve ser uma classe virtual. E abstrata: não deve deixar que ninguém declare Animal. Já te mostrei como fazer e te expliquei porque: não pode deixar que alguém, tipo você mesmo daqui uns meses, tente declarar uma variável da classe Animal, tente copiar, atribuir. Só vai dar problema.


Se está escrevendo isso para um curso vai perder pontos também por isso. E se não perder será uma pena porque indica que não tem professores bons ou atentos.
 

Exclua aquela variável folclórica outraFamilia. Crie uma classe nova. Veja como pode ser simples:
 

class Pet : public Animal
{
private:
    string tipo;
public:
    Pet( string tipo, string nome, char sexo, int idade, float peso, bool outraFamilia );
    string getTipo();
};

 

E quando aparecer um Pet para o qual você ainda não tem classe você simplesmente usa Pet:
 

    Pet* bicho4 = new Pet("Urso Polar", "Urso Branco", 'F', 1, 0.3F, false);
    cout << bicho4->getNome() << endl;
    cout << endl;

 

E poderá atender um esquimó que trouxe um filhote orfão de urso para casa.

 

Um exemplo para o que quer fazer, se eu entendi
 

De todo modo veja essa saída 
 

Criando animais

Gato Bituca
Cao Naja
Ave Azulinha
Urso Branco


Gravando vetor de ponteiros


Acessando atraves do vetor

zoo[0] = class Animal *
Gato Bituca = Gato: Pelagem = branco
zoo[1] = class Animal *
Cao Naja = Cao: Raca = PitBull
zoo[2] = class Animal *
Ave Azulinha = Ave: Especie = araris
zoo[3] = class Animal *
Urso Branco = Outro Pet: Tipo = Pet Generico

 

Deste programa
 

#include <iostream>
#include <typeinfo>
#include <vector>

#include "animal.h"

using namespace std;

int main(void)
{
    cout << "\nCriando animais\n\n";
    Gato* bicho1 = new Gato("branco", true, "", "Gato Bituca", 'M', 0, 0.5, false);
    cout << bicho1->getNome() << endl;
    Cachorro* bicho2 = new Cachorro("PitBull", "marrom", true, false, "Cao Naja", 'F', 5, 15.4F, false);
    cout << bicho2->getNome() << endl;
    Ave* bicho3 = new Ave(false, false, "azul", "araris", 23.3F, "Ave Azulinha", 'F', 1, 0.3F, false);
    cout << bicho3->getNome() << endl;
    Pet* bicho4 = new Pet("Urso Polar", "Urso Branco", 'F', 1, 0.3F, false);
    cout << bicho4->getNome() << endl;
    cout << endl;

    cout << "\nGravando vetor de ponteiros\n\n";
    unique_ptr< vector<Animal*> > zoo(new vector<Animal*>);
    zoo->push_back(bicho1);
    zoo->push_back(bicho2);
    zoo->push_back(bicho3);
    zoo->push_back(bicho4);

    cout << "\nAcessando atraves do vetor\n\n";
    for (unsigned i = 0; i < zoo->size(); i++)
    {
        cout << "zoo[" << i << "] = " << typeid(zoo->at(i)).name() << endl;

        Ave* ave = dynamic_cast<Ave*>(zoo->at(i));
        if (ave != nullptr)
        {
            cout << ave->getNome()
                << " = Ave: Especie = "
                << ave->getEspecie()
                << endl;
            continue;
        };
        Cachorro* cao = dynamic_cast<Cachorro*>(zoo->at(i));
        if (cao != nullptr)
        {
            cout << cao->getNome() 
                << " = Cao: Raca = "
                << cao->getRaca()
                << endl;
            continue;
        };
        Gato* gato = dynamic_cast<Gato*>(zoo->at(i));
        if (gato != nullptr)
        {
            cout << gato->getNome()
                << " = Gato: Pelagem = "
                << gato->getPelagem()
                << endl;
            continue;
        }
        Pet* pet = dynamic_cast<Pet*>(zoo->at(i));
        if (pet != nullptr)
        {
            cout << pet->getNome()
                << " = Outro Pet: Tipo = "
                << pet->getTipo()
                << endl;
            continue;
        }
    };  // for()
    return 0;
}

 

O que importa é esse tipo de construção
 

        cout << "zoo[" << i << "] = " << typeid(zoo->at(i)).name() << endl;
        Ave* ave = dynamic_cast<Ave*>(zoo->at(i));
        if (ave != nullptr)
        {
            cout << ave->getNome()
                << " = Ave: Especie = "
                << ave->getEspecie()
                << endl;
            continue;

 

Que gera por exemplo 
 

zoo[2] = class Animal *
Ave Azulinha = Ave: Especie = araris

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

2 horas atrás, arfneto disse:

Não sei se está escrevendo isso para uso próprio, mas a simples presença de outraFamilia na classe é sinal de que algo está errado. Usando orientação a objetos precisou de uma variável bool para indicar se é uma instância da classe base e isso contradiz a própria filosofia.

Destacando o que o colega disse acima. Não é necessário saber o tipo do objeto e, caso esteja precisando, há um erro de design em suas classes. A forma correta é utilizar os conceitos de herança, polimorfismos, métodos virtuais e sobrecarga.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Flávio Pedroza

32 minutos atrás, Flávio Pedroza disse:

Destacando o que o colega disse acima. Não é necessário saber o tipo do objeto e, caso esteja precisando, há um erro de design em suas classes. A forma correta é utilizar os conceitos de herança, polimorfismos, métodos virtuais e sobrecarga.

 

O exemplo postado aqui foi um recorte do que eu preciso no projeto, coloquei essas partes simplificado na main para não postar o arquivo inteiro. Mas basicamente o container será declarado em uma classe que ficara responsável por cadastrar os Animais.

 

E de que forma o conceito de herança e polimorfismo deve ser usado na classe Animal, já que preciso necessariamente que ela tenha essa forma (classe base: Animal e classes herdeiras: Ave, Cachorro, Gato, Tartaruga )

Link para o comentário
Compartilhar em outros sites

51 minutos atrás, Gabriel Barbosa Brandao disse:

E de que forma o conceito de herança e polimorfismo deve ser usado na classe Animal, já que preciso necessariamente que ela tenha essa forma (classe base: Animal e classes herdeiras: Ave, Cachorro, Gato, Tartaruga )

 

Rodou o programa como te expliquei? Entendeu a diferença? Entendeu o que eu disse sobre a classe Animal?

  • Animal tem que ser abstrata ou só vai complicar sua vida. Apenas não deixe o construtor público
     
  • Use uma classe como a que te mostrei: Pet para  os pets que não tem classe específica
     
  • Não faz diferença onde vai declarar o container. Alocar um ponteiro para o container não é esperto. Todo container é isso: um container. Veja isso de  http://www.cplusplus.com/reference/vector/vector/vector/
    image.thumb.png.8ccd20df6a85c37b6db8b08d85d445ad.png

    É o protótipo do construtor padrão de vetor. Se você tem (a) muito talento e (b) muito tempo e (c) uma necessidade específica, pode escrever com vantagem seu allocator e declarar aí. Eu por exemplo não tenho nenhum dos 3.

    Declarar um ponteiro para um container é folclórico. Se está fazendo isso para uma escola ou vai perder pontos ou tem um instrutor ruim e distraído. 
     
  • Construa seu modelo sem se preocupar com onde está usando o que. Entendo o valor do formalismo, tenho formação em matemática, mas cada programa resolve um problema. Não é preciso inventar modelos para atender paradigmas: Animal é polimórfica. E deveria ser abstrata. Há uma razão para isso. Herança está estabelecida e faz sentido no modelo. Encapsulamento está sendo usado. O modelo em si tem problemas, ao menos como exposto. 
    Qt por exemplo usa herança múltipla. Mas não porque apreciem o conceito: é um recurso para resolver um problema. Começa com o problema.

C++ é uma linguagem sensacional para criar modelos com rapidez E com eficiência. Outras linguagens às vezes tem só a rapidez, outras só a eficiência. Então use o que precisa sem inventar muito. Esse é um modelo simples.

 

  •  A construção que te mostrei faz o que você quer. Rode o exemplo. E incorpore essas coisas em seu código. Poste de novo se precisa de ajuda. Mas mude algo. 
     


Seu programa tem quase os mesmos problemas que tinha quando postou isso 2 semanas atrás.

 

Foi bom que excluiu aquela ideia em torno de
 

class Animal : public QMainWindow{
    Q_OBJECT
private:
    Ui::Animal *ui;

 

Que tinha usado antes. Derivar uma classe do modelo de dados de uma classe do framework não era mesmo uma boa ideia.

Link para o comentário
Compartilhar em outros sites

@arfneto Rodei o código que você me explicou mas o compilador acusou que minha classe não é polimórfica, e não pude usar o dynamic_cast(segue o print do erro)

 

 

Gostaria de usar sim o conceito de polimorfismo e herança em um problema pra exemplificar o uso então pensei na petShop, por isso fiz ela dessa forma.

 

Se me sugerir alguma outra maneira de fazer ela polimórfica sem esses problemas apontados seria sensacional.

 

Sou novo na orientação a objetos com C++, vim do Java mas não me lembro de ter trabalhado com funções virtuais, nem classes abstratas tudo isso ainda é novo pra mim.

Capturar.PNG

Link para o comentário
Compartilhar em outros sites

Minha sugestão é a seguinte:

//Criar o método virutal Imprime dados;
class Animal
{
public:
	(...)
	virtual void Imprimedados() = 0;
}
//Com isso a classe Animal passa a ser abstrada
//Em cada classe filha, você implementará o método de acordo com o tipo
class Gato : public Animal
{
public:
	void Imprimedados() override;
}

class Cachorro : public Animal
{
public:
	void Imprimedados() override;
}
//ect...
//No loop você chamar assim:
for(int i = 0; i < listaDeAnimais->size(); i++)
  {
  listaDeaAnimais[i]->Imprimedados()
  }

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Flávio PedrozaVamos ver se entendi:

  •  void Implementados () seria todas as funções da minha classes ?
  • a classe base não poderá ter atributos privados ?
  • virtual seria uma maneira de possibilitar o trabalho com o polimorfismo ?
  • Todas as funções que eu implementar nas classes filhas precisam estar implementadas na classe base?
  • Qual a função desse override na frente ?

 

Link para o comentário
Compartilhar em outros sites

using namespace std;

class Animal{

protected:
    string nome;
    char sexo; // M|F
    int idade;
    float peso;
    bool outraFamilia; //true = se não for nenhumas das classes filhos
public:
    Animal(string nome, char sexo, int idade, float peso, bool outraFamilia);

    string getNome();
    char getSexo();
    int getIdade();
    float getPeso();
    bool isOutraFamilia();
	//Acrescentar essa linha
	virutal void ImprimeDaddos() = 0;
    //~Animal();
};

class Cachorro : public Animal{
private:
    string raca;
    string pelagem;
    bool adestrado;
    bool castrado;
public:
    Cachorro(string raca, string pelagem, bool adestrado, bool castrado, string nome, char sexo, int idade, float peso, bool outraFamilia);
    string getRaca();
	//Acrescentar essa linha
	void ImprimeDaddos() override;
};

class Gato : public Animal{
private:
    string pelagem;
    bool castrado;
    string observacao;
public:
    Gato(string pelo, bool castrado, string observacao, string nome, char sexo, int idade, float peso, bool outraFamilia);
    string getPelagem();
	//Acrescentar essa linha
	void ImprimeDaddos() override;
};

class Ave : public Animal{
private:
    bool dieta;
    bool gaiola;
    string penugem;
    string especie;
    float invergadura;
public:
    Ave(bool dieta, bool gaiola, string penugem, string especie, float invergadura, string nome, char sexo, int idade, float peso, bool outraFamilia);
    bool isDieta();
    string getEspecie();
	//Acrescentar essa linha
    void ImprimeDaddos() override;
};

class Tartaruga : public Animal{
private:
    bool dieta;
    string tipoDeAmbiente;
    float tamanhoDaCarapaca;
public:
    Tartaruga(bool dieta, string tipoDeAmbiente, float tamanhoDaCarapaca, string nome, char sexo, int idade, float peso, bool outraFamilia);
    bool isDieta();
    string getTipoDeAmbiente();
    float getTamanhoDaCarapaca();
	void ImprimeDaddos() override;
};


#endif // ANIMAL_H
 

 

animal.cpp


#include "animal.h"

using namespace std;

Animal::Animal(string nome, char sexo, int idade, float peso, bool outraFamilia){
    this->nome = nome;
    this->sexo = sexo;
    this->idade = idade;
    this->peso = peso;
    this->outraFamilia = outraFamilia;
}

string Animal::getNome(){
    return this->nome;
}

char Animal::getSexo(){
    return this->sexo;
}

int Animal::getIdade(){
    return this->idade;
}

float Animal::getPeso(){
    return this->peso;
}

bool Animal::isOutraFamilia(){
    return this->outraFamilia;
}


Cachorro::Cachorro(string raca, string pelagem, bool adestrado, bool castrado, string nome, char sexo, int idade, float peso, bool outraFamilia):Animal(nome, idade, sexo, peso, outraFamilia){
    this->raca = raca;
    this->pelagem = pelagem;
    this->adestrado = adestrado;
    this->castrado = castrado;
}

string Cachorro::getRaca(){
    return this->raca;
}

void Cachorro::ImprimeDados()
{
cout << cao->getNome() 
                << " = Cao: Raca = "
                << cao->getRaca()
                << endl;
            continue;
}

Gato::Gato(string pelagem, bool castrado, string observacao, string nome, char sexo, int idade, float peso, bool outraFamilia):Animal(nome, idade, sexo, peso, outraFamilia){
    this->pelagem = pelagem;
    this->castrado = castrado;
    this->observacao = observacao;
}

string Gato::getPelagem(){
    return this->pelagem;
}

void Gato::ImprimeDados()
{
cout << gato->getNome()
                << " = Gato: Pelagem = "
                << gato->getPelagem()
                << endl;
            continue;
}

Ave::Ave(bool dieta, bool gaiola, string penugem, string especie, float invergadura, string nome, char sexo, int idade, float peso, bool outraFamilia):Animal(nome, sexo, idade, peso, outraFamilia){
    this->dieta = dieta;
    this->gaiola = gaiola;
    this->penugem = penugem;
    this->especie = especie;
    this->invergadura = invergadura;
}

bool Ave::isDieta(){
    return this->dieta;
}
string Ave::getEspecie(){
    return this->especie;
}
void Ave::ImprimeDados()
{
 cout << ave->getNome()
                << " = Ave: Especie = "
                << ave->getEspecie()
                << endl;
            continue;
}

Tartaruga::Tartaruga(bool dieta, string tipoDeAmbiente, float tamanhoDaCarapaca, string nome, char sexo, int idade, float peso, bool outraFamilia) : Animal(nome, sexo, idade, peso, outraFamilia){
    this->dieta = dieta;
    this->tipoDeAmbiente = tipoDeAmbiente;
    this->tamanhoDaCarapaca = tamanhoDaCarapaca;
}

bool Tartaruga::isDieta(){
    return this->dieta;
}

string Tartaruga::getTipoDeAmbiente(){
    return tipoDeAmbiente;
}

float Tartaruga::getTamanhoDaCarapaca(){
    return this->tamanhoDaCarapaca;
}

void Tartaruga::ImprimeDados()
{
	cout << "I like turtle.\n";
}

Desse jeito aí de cima (pode ter alguns erros de sintaxe, não testei):

1. ImprimeDados() - não, é só uma função para mostrar algo na tela ou qq outra coisa que você queira (veja no exemplo acima);

2. A classe base pode ter qualquer coisa, não há limitação

3. Sim

4. Não

5. Para garantir que o método é virtual e está está sobrescrevendo outro método virtual

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Solução
57 minutos atrás, Flávio Pedroza disse:

Minha sugestão é a seguinte:

 

58 minutos atrás, Flávio Pedroza disse:

//Criar o método virutal Imprime dados;

 

@Flávio Pedroza pode usar o próprio getNome() para isso. 


Isso porque pode ser até vantagem redefinir getNome() nas subclasses e acrescentar o tipo de animal no nome, algo como no exemplo getNome() retornar "[Gato] Felix" para um Gato chamado Felix, usando um override.

 

Por outro lado, 


 

1 hora atrás, Gabriel Barbosa Brandao disse:

Gostaria de usar sim o conceito de polimorfismo e herança em um problema pra exemplificar o uso então pensei na petShop, por isso fiz ela dessa forma


Para a classe ser polimórfica basta declarar algum dos métodos como virtual. Desculpe não ter explicado. Eu ia postar o exemplo e esqueci. Mas eu te disse já umas vezes: Animal deve ser abstrata, não apenas virtual. Vai dar m3rd@ se declarar um Animal, copiar um ponteiro, atribuir. A ideia de uma classe abstrata é exatamente o que você procura: definir uma classe de onde outras derivam. Apenas. Crie uma genérica para os outros bichos e poderá abrir mão daquela variável folclórica outraFamilia por exemplo. Veja a classe Pet que te mostrei.

 

Repito minha sugestão: não queira usar algo antes de seu programa precisar desse algo. No seu programa do modo como construiu faz sentido usar um container de ponteiros para uma classe base abstrata. Use. Deixe a natureza dos problemas guiar a implementação e apenas estude os conceitos.

 

1 hora atrás, Gabriel Barbosa Brandao disse:

Sou novo na orientação a objetos com C++, vim do Java mas não me lembro de ter trabalhado com funções virtuais, nem classes abstratas tudo isso ainda é novo pra mim


Em java é igualzinho. Se usa uma anotação @override para indicar o caso. 

 

Ainda sobre isso note que às vezes quer justamente o contrário e impedir esse caso, e aí usa o especificador final, em C++ ou java


Exemplo em seu programa
 

class Gato : public Animal
{
private:
    string pelagem;
    bool castrado;
    string observacao;
public:
    Gato(string pelo, bool castrado, string observacao, 
         string nome, char sexo, int idade,
         float peso, bool outraFamilia);
    string getNome() final;
    string getPelagem();
};

 

Eu não sei ao certo os termos em português para explicar essas coisas porque estudei C++ em aulas ou tive livros em português, mas entenda que nesse caso getNome() é uma função virtual pura em C++. Da classe Animal. E isso quer dizer que toda classe derivada dessa deve implementar sua versão de getNome(). E se ela não fizer isso passa a ser abstrata também. E tudo isso é muito legal porque o compilador garante que todo mundo vai cooperar.

 

E quando você tem uma situação em que tem que dar um na cadeia de redefinições você usa como está acima: define o método como final. 

 

Animal poderia ser assim:
 

class Animal
{
protected:
    string nome;
    char   sexo; // M|F
    int    idade;
    float  peso;
    Animal(string nome, char sexo, int idade, float peso);

public:
    virtual string getNome() = 0;
    char getSexo();
    int getIdade();
    float getPeso();
    bool isOutraFamilia();
};

 

oficialmente abstrata, virtual e polimórfica. Mas com sentido nesse contexto do seu modelo.

 

Em java você pode definir uma classe de fato como abstrata declarando abstract class. Em C++ não tem essa especificação mas você pode tornar Animal abstrata além de virtual ou polimórfica declarando como acima

 

1 hora atrás, Gabriel Barbosa Brandao disse:
  • void Implementados () seria todas as funções da minha classes ?
  • a classe base não poderá ter atributos privados ?
  • virtual seria uma maneira de possibilitar o trabalho com o polimorfismo ?
  • Todas as funções que eu implementar nas classes filhas precisam estar implementadas na classe base?
  • Qual a função desse override na frente ?

 

Com a licença de @Flávio Pedroza apenas para o texto ficar completo:


- O primeiro item não entendi.
 

- Nada dessa discussão tem a ver com os modificadores de acesso da classe base. Os atributos são definidos conforme o modelo exigir.
 

- ao menos um método virtual define uma classe como polimórfica
 

- só precisa implementar as que estiverem marcadas como pure virtual --- =0 --- na classe base, que é dita abstrata como em java
 

- override é opcional em C++ mas é um indicador para você e para o compilador de que está redefinindo a função de propósito.

 

 

 

Esqueci do exemplo de novo. Alterei um pouco para incorporar essa discussão de hoje

 

Saida
 


Criando animais

Gato Bituca
Cao Naja
Ave Azulinha
Urso Branco

Gravando vetor de ponteiros


Acessando atraves do vetor

zoo[0] = class Animal *
Gato Bituca = Gato: Pelagem = branco
zoo[1] = class Animal *
Cao Naja = Cao: Raca = PitBull
zoo[2] = class Animal *
Ave Azulinha = Ave: Especie = araris
zoo[3] = class Animal *
Urso Branco = Outro Pet: Tipo = Pet Generico

 

O programa é mínimo

int main(void)
{
    cout << "\nCriando animais\n\n";
    Gato* bicho1 = new Gato("branco", true, "", "Gato Bituca", 'M', 0, 0.5);
    cout << bicho1->getNome() << endl;
    Cachorro* bicho2 = new Cachorro("PitBull", "marrom", true, false,
        "Cao Naja", 'F', 5, 15.4F);
    cout << bicho2->getNome() << endl;
    Ave* bicho3 = new Ave(false, false, "azul", "araris",
        23.3F, "Ave Azulinha", 'F', 1, 0.3F);
    cout << bicho3->getNome() << endl;
    Pet* bicho4 = new Pet("Urso Polar",
        "Urso Branco", 'F', 1, 0.3F);
    cout << bicho4->getNome() << endl;
    cout << endl;

    cout << "\nGravando vetor de ponteiros\n\n";
    unique_ptr< vector<Animal*> > zoo(new vector<Animal*>);
    zoo->push_back(bicho1);
    zoo->push_back(bicho2);
    zoo->push_back(bicho3);
    zoo->push_back(bicho4);

    cout << "\nAcessando atraves do vetor\n\n";
    for (unsigned i = 0; i < zoo->size(); i++)
    {
        cout << "zoo[" << i << "] = " << typeid(zoo->at(i)).name() << endl;
        Ave* ave = dynamic_cast<Ave*>(zoo->at(i));
        if (ave != nullptr)
        {
            cout << ave->getNome()
                << " = Ave: Especie = "
                << ave->getEspecie()
                << endl;
            continue;
        };
        Cachorro* cao = dynamic_cast<Cachorro*>(zoo->at(i));
        if (cao != nullptr)
        {
            cout << cao->getNome() 
                << " = Cao: Raca = "
                << cao->getRaca()
                << endl;
            continue;
        };
        Gato* gato = dynamic_cast<Gato*>(zoo->at(i));
        if (gato != nullptr)
        {
            cout << gato->getNome()
                << " = Gato: Pelagem = "
                << gato->getPelagem()
                << endl;
            continue;
        }
        Pet* pet = dynamic_cast<Pet*>(zoo->at(i));
        if (pet != nullptr)
        {
            cout << pet->getNome()
                << " = Outro Pet: Tipo = "
                << pet->getTipo()
                << endl;
            continue;
        }
    };  // for()
    return 0;
}

 

Apenas cria os bichos e põe no vetor e chama um método de cada um.

 

Animal.h:

 

Spoiler

#pragma once
#include <iostream>
#include <string>
using namespace std;

class Animal
{
protected:
    string nome;
    char   sexo; // M|F
    int    idade;
    float  peso;
    Animal(string nome, char sexo, int idade, float peso);

public:
    virtual string getNome() = 0;
    char getSexo();
    int getIdade();
    float getPeso();
};

class Cachorro : public Animal
{
private:
    string raca;
    string pelagem;
    bool adestrado;
    bool castrado;
public:
    Cachorro(string raca, string pelagem, 
        bool adestrado, bool castrado, string nome,
        char sexo, int idade, float peso);
    virtual string getNome();
    string getRaca();
};

class Gato : public Animal
{
private:
    string pelagem;
    bool castrado;
    string observacao;
public:
    Gato(string pelo, bool castrado, string observacao,
        string nome, char sexo, int idade, float peso);
    string getNome() final;
    string getPelagem();
};

class Ave : public Animal
{
private:
    bool dieta;
    bool gaiola;
    string penugem;
    string especie;
    float invergadura;
public:
    Ave(bool dieta, bool gaiola, string penugem,
        string especie, float invergadura,
        string nome, char sexo, int idade, float peso);
    virtual string getNome();
    bool isDieta();
    string getEspecie();
};

class Tartaruga : public Animal
{
private:
    bool dieta;
    string tipoDeAmbiente;
    float tamanhoDaCarapaca;
public:
    Tartaruga(bool dieta, string tipoDeAmbiente,
        float tamanhoDaCarapaca, string nome,
        char sexo, int idade, float peso);
    virtual string getNome();
    bool isDieta();
    string getTipoDeAmbiente();
    float getTamanhoDaCarapaca();
};

class Pet : public Animal
{
private:
    string tipo;
public:
    Pet( string tipo, string nome, char sexo, int idade, float peso);
    virtual string getNome();
    string getTipo();
};

 

 

Animal.cpp

Spoiler

#include "animal.h"

using namespace std;

Animal::Animal(string nome, char sexo, int idade, float peso)
{
    this->nome = nome;
    this->sexo = sexo;
    this->idade = idade;
    this->peso = peso;
}

char Animal::getSexo() {
    return this->sexo;
}

int Animal::getIdade() {
    return this->idade;
}

float Animal::getPeso() {
    return this->peso;
}


Cachorro::Cachorro(
    string raca, string pelagem, bool adestrado,
    bool castrado, string nome, char sexo,
    int idade, float peso)
    : Animal(nome, sexo, idade, peso)
{
    this->raca = raca;
    this->pelagem = pelagem;
    this->adestrado = adestrado;
    this->castrado = castrado;
}

string Cachorro::getNome()
{ 
    return nome;
}

string Cachorro::getRaca() {
    return this->raca;
}

Gato::Gato(string pelagem, bool castrado, string observacao, string nome, char sexo, int idade, float peso)
    :Animal(nome, idade, sexo, peso) {
    this->pelagem = pelagem;
    this->castrado = castrado;
    this->observacao = observacao;
}

string Gato::getNome()
{
    return nome;
}

string Gato::getPelagem() {
    return this->pelagem;
}

Ave::Ave(bool dieta, bool gaiola, string penugem, string especie, float invergadura, string nome, char sexo, int idade, float peso) 
    :Animal(nome, sexo, idade, peso)
{
    this->dieta = dieta;
    this->gaiola = gaiola;
    this->penugem = penugem;
    this->especie = especie;
    this->invergadura = invergadura;
}

string Ave::getNome()
{
    return nome;
}

bool Ave::isDieta() {
    return this->dieta;
}
string Ave::getEspecie() {
    return this->especie;
}

Tartaruga::Tartaruga(bool dieta, string tipoDeAmbiente, float tamanhoDaCarapaca, string nome, char sexo, int idade, float peso)
    : Animal(nome, sexo, idade, peso)
{
    this->dieta = dieta;
    this->tipoDeAmbiente = tipoDeAmbiente;
    this->tamanhoDaCarapaca = tamanhoDaCarapaca;
}

string Tartaruga::getNome()
{
    return nome;
}

bool Tartaruga::isDieta() {
    return this->dieta;
}

string Tartaruga::getTipoDeAmbiente() {
    return tipoDeAmbiente;
}

float Tartaruga::getTamanhoDaCarapaca() {
    return this->tamanhoDaCarapaca;
}

Pet::Pet(string tipo, string nome, char sexo, int idade, float peso)
    : Animal(nome, sexo, idade, peso), tipo("Pet Generico")
{}

string Pet::getNome()
{
    return nome;
}


string Pet::getTipo()
{ 
    return tipo;
}

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

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...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!