Форвардная декларация и typeid - PullRequest
2 голосов
/ 16 декабря 2009

Я хотел бы проверить тип суперкласса 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’

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

Ответы [ 6 ]

3 голосов
/ 16 декабря 2009

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

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


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

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

1 голос
/ 16 декабря 2009

Просто переместите определение Check () из тела 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;
}
0 голосов
/ 16 декабря 2009

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

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

0 голосов
/ 16 декабря 2009

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

Переместите ваше определение чека ниже декларации класса B.

0 голосов
/ 16 декабря 2009

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

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

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