Вопрос

Я хотел бы проверить тип суперкласса A против типа подкласса B (с помощью метода внутри суперкласса A, так что B унаследует его).

Вот что, как я думал, помогло (то есть использование прямого объявления):

#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;
}

Однако этот код не компилируется.Ошибка, которую я получаю, это:

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’

Как я мог бы решить эту проблему?

Это было полезно?

Решение

Я думаю, что проблема, которую вы пытаетесь решить, гораздо лучше решается виртуальным методом:

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


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

Методам в базовом классе A не нужно знать, является ли объект "действительно" A или a B.Это нарушение основных принципов объектно-ориентированного проектирования.Если поведение должно измениться, когда объект является B, то это поведение должно быть определено в B и обрабатываться вызовами виртуальных методов.

Другие советы

Просто переместите определение Check() из тела:

#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;
}

Одним из способов было бы извлечь определение Check из определения класса, так что B определяется, когда компилятор переходит к определению функции.

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

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

Переместите ваше определение проверки ниже вашего объявления класса B.

Просто переместите тело функции после объявления 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;
}

Привет, даже если вы поместите определение A::Check за пределы класса, результат будет не таким, как вы ожидаете.Это связано с тем, что объект B преобразуется в объект A в методе, поэтому это указывает на объект A, поэтому идентификаторы типов всегда разные.Чтобы решить эту проблему, объявите метод virtual.

Однако я все еще не понимаю, почему вы хотите выполнить такой тест O_o ??И, как сказал Кадакер, это не очень хорошая практика

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top