2008-09-22 5 views
7

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

ответ

37

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

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

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

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

class B 
{ 
public: 
    A *itemA; 
}; 

class A 
{ 
public: 
    B *itemB; 
}; 
+0

... или ссылка на один: MyClass & rMyObject; – 2008-09-22 06:09:12

0

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

+0

Я на самом деле пытаюсь сделать обратное, где первый класс ссылается на второй класс, а второй класс содержит экземпляры первого класса. – 2008-09-22 14:03:04

0

Это называется перекрестная ссылка. См. Пример here.

2

Есть an elegant solution с помощью шаблонов.

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

Интересный (хотя он содержит несколько опечаток). Но «getA» и «getB» - действительно фабрики: они возвращают новые экземпляры (по значению). У экземпляра A нет - a B, а экземпляр B - A. – jwfearn 2008-09-23 00:50:11