Pergunta

Eu gostaria de verificar o tipo de superclasse A contra o tipo de subclasse B (com um método dentro da superclasse A, para que B irá herdar).

Aqui está o que eu pensei que fiz o truque (isto é, o uso da declaração avançada):

#include <iostream>
#include <typeinfo>

using namespace std;

class B;

class A {
  public:
    int i_;
    void Check () {
      if (typeid (*this) == typeid (B))
        cout << "True: Same type as B." << endl;
      else
        cout << "False: Not the same type as B." << endl;
    }
};

class B : public A {
  public:
    double d_;
};


int main () {

  A a;
  B b;

  a.Check (); // should be false
  b.Check (); // should be true

  return 0;
}

No entanto, este código não compila. O erro que recebo é:

main.cc: In member function ‘void A::Check()’:
main.cc:12: error: invalid use of incomplete type ‘struct B’
main.cc:6: error: forward declaration of ‘struct B’

Como eu poderia resolver esse problema?

Foi útil?

Solução

Eu acho que o problema que você está tentando resolver é muito melhor tratado por um método virtual:

class A
{
    public:
        virtual bool Check() { return false; };
}


class B : public A
{
    public:
        // override A::Check()
        virtual bool Check() { return true; };
}

Os métodos na classe Base A não precisam saber se o objeto é "realmente" um A ou A B. Isso é uma violação dos princípios básicos de design orientados a objetos. Se o comportamento precisar mudar quando o objeto for B, esse comportamento deve ser definido em B e tratado por chamadas de método virtual.

Outras dicas

Basta mover a definição de check () para fora do corpo de A:

#include <iostream>
#include <typeinfo>

using namespace std;

class B;

class A {
  public:
    int i_;
    void Check ();
};

class B : public A {
  public:
    double d_;
};

void A::Check () {
  if (typeid (*this) == typeid (B))
    cout << "True: Same type as B." << endl;
  else
    cout << "False: Not the same type as B." << endl;
}

int main () {

  A a;
  B b;

  a.Check (); // should be false
  b.Check (); // should be true

  return 0;
}

Uma maneira seria puxar a definição de Check fora da definição de classe, de modo que B é definido quando o compilador chega à definição da função.

class A {
    //...
    void Check();
    //...
};
class B { /* ... */ };

void A::Check() {
    //...
}

Mova sua definição da verificação abaixo da sua declaração da classe B.

Basta mover o corpo da função após a declaração de B.

#include <iostream>
#include <typeinfo>

struct A
{
    int i_;
    void Check();
};

struct B :  A
{
    double d_;
};

void A::Check()
{
    using namespace std;
    if (typeid (*this) == typeid (B))
    {
        cout << "True: Same type as B." << endl;
    }
    else
    {
        cout << "False: Not the same type as B." << endl;
    }
}

int main()
{
    A a;
    B b;

    a.Check(); // should be false
    b.Check(); // should be true

    return 0;
}

Olá, mesmo se você colocar a definição de A :: Check fora da classe, o resultado não será o que você espera. Isso ocorre porque o objeto B que isso é convertido para um objeto A no método, para que este ponto em um objeto A, portanto, os tipos são sempre diferentes. Para resolver isso, declare o método virtual.

No entanto, ainda não entendo por que você quer realizar esse teste O_O ?? E como o Cadaker disse que isso não é uma boa prática

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top