Объявите объект еще до того, как этот класс будет создан - PullRequest
8 голосов
/ 22 сентября 2008

Есть ли способ объявить объект класса перед тем, как класс будет создан в C ++? Я спрашиваю, потому что я пытаюсь использовать два класса, первый должен иметь экземпляр второго класса, но второй класс также содержит экземпляр первого класса. Я понимаю, что вы можете подумать, что я могу попасть в бесконечный цикл, но мне действительно нужно создать и экземпляр второго класса перед первым классом.

Ответы [ 5 ]

39 голосов
/ 22 сентября 2008

Вы не можете сделать что-то вроде этого:

class A {
    B b;
};
class B {
    A a;
};

Самая очевидная проблема в том, что компилятор не знает, как много нужно для создания класса A, поскольку размер B зависит от размера A!

Однако вы можете сделать это:

class B; // this is a "forward declaration"
class A {
    B *b;
};
class B {
    A a;
};

Объявление класса B в качестве прямого объявления позволяет вам использовать указатели (и ссылки) на этот класс, не имея при этом полного определения класса.

5 голосов
/ 22 сентября 2008

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

class A;  // Declare that we have a class A without defining it yet.

class B
{
public:
    A *itemA;
};

class A
{
public:
    B *itemB;
};
2 голосов
/ 22 сентября 2008

Есть элегантное решение с использованием шаблонов.

template< int T > class BaseTemplate {};
typedef BaseTemplate< 0 > A;
typedef BaseTemplate< 1 > B;
// A
template<> class BaseTemplate< 0 >
{
public:
   BaseTemplate() {} // A constructor
   B getB();
}

// B
template<> class BaseTemplate< 1 >
{
public:
   BaseTemplate() {} // B constructor
   A getA();
}

inline B A::getB() { return A(); }
inline A B::getA() { return B(); }

Этот код будет работать! Итак, почему это Работа? Причина связана с тем, как шаблоны скомпилированы. Шаблоны задержать создание функции подписи, пока вы на самом деле не используете шаблон где-то. Это означает, что ни getA (), ни getB () не будут иметь их подписи анализируются до оба класса A и B уже были полностью заявлено. Это магия этот метод.

0 голосов
/ 22 сентября 2008

Это называется перекрестной ссылкой. См. здесь пример.

0 голосов
/ 22 сентября 2008

Это близко к тому, что вы хотите: первый класс содержит второй класс, но второй класс (который должен быть создан первым) просто имеет ссылку на первый класс?

...