C ++: Как использовать типы, которые не были определены? - PullRequest
4 голосов
/ 03 июня 2010

C ++ требует, чтобы все типы были определены до того, как их можно будет использовать, поэтому важно включать заголовочные файлы в правильном порядке. Хорошо. Но как насчет моей ситуации:

Bunny.h * * 1004

   class Bunny
   {
       ...
   private:
       Reference<Bunny> parent;
   }

Компилятор жалуется, потому что технически Bunny не был полностью определен в момент, когда я использую его в своем определении класса. , потому что я сделал что-то глупое ( не связано ) .

Помимо переписывания моего шаблонного класса Reference, так что он принимает тип указателя (в этом случае я могу использовать прямое объявление Bunny), я не знаю, как решить эту проблему.

Есть предложения?

РЕДАКТИРОВАТЬ: Мой Reference класс (XObject является базовым классом для объектов режима данных):

template <class T = XObject> class Reference
{
public:
    Reference() : m_ptr (NULL) {}
    Reference(T* p)
    {
        m_ptr = p;
        if (p != NULL) ((XObject*)p)->ref();
    }
    ~Reference()
    {
        if (m_ptr)
        {
            ((XObject*)m_ptr)->deref();
        }
    }

    // ... assignment, comparison, etc.

private:
    T* m_ptr;
}; 

EDIT : Это работает нормально, проблема была в другом. Большое спасибо за вашу помощь!

Ответы [ 3 ]

3 голосов
/ 03 июня 2010

Ответ на ваш вопрос зависит от того, как выглядит Ссылка <>. Если в нем есть переменная экземпляра типа Bunny, то, конечно, она не будет работать (как бы это было, у вас есть рекурсивное определение, которое никогда не заканчивается). Если он содержит только ссылки и указатели, он должен работать нормально. Тип Bunny в экземпляре шаблона не будет мешать этому.

Редактировать (разместить ссылку <> редактирование кода):

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

struct base {
  void fun() {}
};
template < typename T >
struct temp
{
  T * t;

  void f() { ((base*)t)->fun(); }
};

struct test
{
  temp<test> t;

};

int main()
{
  test t;
  t.t.f();
}

Это явно неверный код, потому что вы получите неопределенные результаты, но он компилируется. Главной проблемой здесь является переинтерпретация приведения типа test * к типу base *. Если тест действительно наследовал от базы, то приведение даже не понадобилось бы. Код, подобный этому, не будет функционировать должным образом, но он должен хорошо компилироваться. Одна рекомендация, которую я бы дал, - это потерять все броски в стиле с. Это не решит проблему, которая у вас есть, что бы это ни было ... это должно быть где-то в коде, который вы не вставляете.

1 голос
/ 03 июня 2010

Если Reference<T> имеет переменную типа T, то T не может иметь переменную типа Reference<T>. Ваши альтернативы: либо переписать Reference<T>, либо переписать Bunny, чтобы использовать указатель на Reference<T>:

template<class> class Reference;

class Bunny
{
    ...
private:
    Reference<Bunny>* parent;
}
0 голосов
/ 03 июня 2010

Разве это не просто вопрос абстракции, где абстракция становится решением проблемы? Я хотел бы создать интерфейс IBunny, а затем использовать Reference<IBunny> внутри любого определения, которое реализует IBunny.

Это один из тех сценариев использования, для которых были изобретены интерфейсы (удобно в типичных шаблонах создания GoF).

...