Ir ao conteúdo
  • Cadastre-se

C++ Como separar/identificar classes filhas em um vector do tipo pai


Paulo Estêvão

Posts recomendados

Bom dia, gente.

Estou com um problema sobre como separar/identificar classes filhas em um vector do tipo pai. Tenho uma classe abstrata chamada Pessoa e outras duas classes, Amigo e Conhecido, que herdam de maneira public Pessoa. A classe Pessoa tem dois atributos, nome e idade, a classe  Amigo tem um atributo aniversario e a classe Conhecido tem um atributo chamado e-mail. Eu instancio vários objetos do tipo Amigo e Conhecido e coloco dentro de um vector do tipo Pessoa. Acontece que em determinado ponto tenho que imprimir as datas de aniversário, só obj Amigo possui tal atributo, e também  tenho que imprimir os e-mails, só obj Conhecido tem tal atributo.  Como eu disse antes todos os obj ficam no meu vector do tipo Pessoa. Eu gostaria de saber se tem alguma forma de eu iterar meu vector e identificar se um objeto é um Amigo ou Conhecido e a partir disso imprimir o que se pede, ou se tem uma solução para que eu consiga chegar no resultado. Eu pensei em no momento da instanciação dos objetos eu colocar cada qual em um vector específico para seu tipo e depois usar um for each em cada vector e imprimir o que se pede, entretanto a proposta é fazer tudo usando esse vector mais geral.

Link para o comentário
Compartilhar em outros sites

C++ não tem o que quer, que seria instanceof() que tem em java. O mais próximo que eu conheço em C++  é dynamic_cast<Amigo *>(x) que retorna NULL se x não for Amigo.

 

Não está de fato usando classes mas apenas campos de estruturas. Talvez fosse mais simples usar o que se chamava variant record em Pascal, e usar Pessoa como struct e uma union no final, como em C.

 

Ou mesmo usar std::variant em C++

 

Como indicado no tópico acima, através de um link,  pode usar em C++20, derived_from, que eu suspeito que seja a mesma coisa internamente.

 

EXEMPLOS

 

#include <concepts>
#include <iostream>
#include <vector>
using namespace std;

class Pessoa
{
public:
     virtual void metodo(){};
};

class Amigo : public Pessoa{};
class Conhecido : public Pessoa{};

int main(void)
{
    vector<Pessoa*>      alguem;
    Amigo       amigo;
    Conhecido   conhecido;

    for( int i=0; i<10; i+=2 )
    {
        alguem.push_back(&amigo);  // par
        alguem.push_back(&conhecido); // impar = conhecido
    };

    for( int i=0; i<10; i+=1 )
    {
        Amigo* a =  	dynamic_cast<Amigo *> ( alguem[i] );
        if ( a != NULL )
        {
            cout << i << ":  Amigo\n";
        }
        else
        {
            Conhecido* c =  dynamic_cast<Conhecido *> ( alguem[i] );
            if ( c != NULL ) cout << i << ":  Conhecido\n";
        }
    };

    if ( std::derived_from<Amigo, Pessoa> )
        cout << "Amigo deriva de Pessoa\n";

    if ( not std::derived_from<Pessoa, Amigo> )
        cout << "Pessoa nao deriva de Amigo\n";

    if ( std::derived_from<Conhecido, Pessoa> )
        cout << "Conhecido deriva de Pessoa\n";
    return 0;

};

 

Isso aí preenche um vetor com 10 ponteiros para Pessoa. As pares são amigas. E retorna

 

PS C:\src> g++ -o ./teste -Wall -O3 -std=c++2a vp.cpp
PS C:\src> ./teste
0:  Amigo
1:  Conhecido
2:  Amigo
3:  Conhecido
4:  Amigo
5:  Conhecido
6:  Amigo
7:  Conhecido
8:  Amigo
9:  Conhecido
Amigo deriva de Pessoa
Pessoa nao deriva de Amigo
Conhecido deriva de Pessoa

 

Usando struct e variant podia ser como abaixo

 

#include <iostream>
#include <string>
#include <variant>
#include <vector>
using namespace std;

typedef struct
{ string  aniversario; } Amigo;

typedef struct 
{ string e_mail; } Conhecido;

typedef struct 
{
    string nome;
    unsigned idade;
    std::variant<Amigo,Conhecido> r;

}   Pessoa;

int main(void)
{
    vector<Pessoa*>      alguem;
    Amigo       amigo;
    amigo.aniversario = "12/12/12";
    Conhecido   conhecido;
    conhecido.e_mail = "[email protected]";

    Pessoa uma{ "pessoa amiga",12};
    uma.r = amigo;
    Pessoa outra{ "pessoa conhecida",22};
    outra.r = conhecido;

    for( int i=0; i<10; i+=2 )
    {
        alguem.push_back(&uma);  // par
        alguem.push_back(&outra); // impar = conhecido
    };

    for( int i=0; i<10; i+=1 )
    {
        cout << i << ": " << alguem[i]->nome << "," << alguem[i]->idade;
        if ( std::holds_alternative<Amigo>(alguem[i]->r) )
            cout << ". Amigo, aniversario " << 
            std::get<Amigo>(alguem[i]->r).aniversario << endl;

        if ( std::holds_alternative<Conhecido>(alguem[i]->r) )
            cout << ". Conhecido, e-mail " << 
            std::get<Conhecido>(alguem[i]->r).e_mail << endl;

    };
    return 0;

};

 

Que faz quase a mesma coisa e mostra
 

0: pessoa amiga,12. Amigo, aniversario 12/12/12
1: pessoa conhecida,22. Conhecido, e-mail [email protected]
2: pessoa amiga,12. Amigo, aniversario 12/12/12
3: pessoa conhecida,22. Conhecido, e-mail [email protected]
4: pessoa amiga,12. Amigo, aniversario 12/12/12
5: pessoa conhecida,22. Conhecido, e-mail [email protected]
6: pessoa amiga,12. Amigo, aniversario 12/12/12
7: pessoa conhecida,22. Conhecido, e-mail [email protected]
8: pessoa amiga,12. Amigo, aniversario 12/12/12
9: pessoa conhecida,22. Conhecido, e-mail [email protected]

 

 

Só que aí pode usar um compilador mais antigo

 

Atente para as diferenças. Se for usar union é  mais simples. Note que é um exemplo primário e são ponteiros para as mesmas coisas. ;) estou sem tempo e nada acrescentaria

 

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!