Когда вы объявляете своего члена, вы все еще определяете класс A
, поэтому тип A
все еще не определен.
Однако, когда вы пишете A*
, компилятор уже знает, что A
обозначает имя класса, и поэтому тип "указатель на A" определен . Вот почему вы можете вставить указатель на тип, который вы определяете.
Та же логика применима и к другим типам, поэтому если вы просто напишите:
class Foo;
Вы объявляете класс Foo, но никогда не определяете его. Вы можете написать:
Foo* foo;
Но не:
Foo foo;
С другой стороны, какую структуру памяти вы бы ожидали для вашего типа A
, если бы компилятор допускал рекурсивное определение?
Однако иногда логически допустимо иметь тип, который как-то ссылается на другой экземпляр того же типа. Люди обычно используют указатели для этого или даже лучше: умные указатели (например, boost::shared_ptr
), чтобы избежать необходимости ручного удаления.
Что-то вроде:
class A
{
private:
boost::shared_ptr<A> member;
};