"Неполный тип" в классе, который имеет член того же типа самого класса

У меня есть класс, который должен иметь отдельный член того же класса, что-то вроде:

class A {
    private:
        A member;
}

но он говорит мне, что member является неполным типом. Почему? Он не говорит мне неполный тип, если я использую указатель, но я бы предпочел не использовать указатель. Любая помощь приветствуется

8 ответов


в то время, когда вы объявляете своего члена, Вы все еще определение the A класс, так типа A по-прежнему не определено.

однако, когда вы пишете A*, компилятор уже знает, что A означает имя класса, поэтому тип "указатель на A" -определена. Вот почему вы можете встроить указатель на тип, который вы определяете.

та же логика применяется и для других типов, поэтому, если вы просто пиши:

class Foo;

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

Foo* foo;

но нет:

Foo foo;

С другой стороны, какую структуру памяти вы ожидаете для своего типа A если компилятор разрешил рекурсивное определение ?

однако иногда логически допустимо иметь тип, который каким-то образом ссылается на другой экземпляр того же типа. Люди обычно используют указатели для этого или даже лучше: умные указатели (как boost::shared_ptr), чтобы избежать необходимости иметь дело с ручного удаления.

что-то типа:

class A
{
  private:
    boost::shared_ptr<A> member;
};

Это рабочий пример того, что вы пытаетесь достичь:

class A {
public:
    A() : a(new A()) {}
    ~A() { delete a; a = nullptr; }
private:
    A* a;
};

A a;

Счастливое Переполнение Стека!


A является "неполным" до конца его определения (хотя это не включает тела функций-членов).

одна из причин этого заключается в том, что, пока определение не закончится, нет никакого способа узнать, насколько велик A is (что зависит от суммы размеров членов плюс несколько других вещей). Ваш код является отличным примером этого: ваш тип A определяется размером типа A.

ясно, объект типа A может не содержать объект-член, который также имеет тип A.

вам нужно будет сохранить указатель или ссылку; желание сохранить либо, возможно, подозревается.


вы не можете включить A в A. Если вы смогли это сделать, и вы объявили, например,A a;, вам нужно будет обратиться к a.member.member.member... бесконечно. У вас не так много ОЗУ.


Как пример class A также содержит другой экземпляр class A?

он может содержать указатель на A, если вы хотите.


этот тип ошибки возникает при попытке использовать класс, который еще не полностью определен.

попробуйте использовать .


проблема возникает, когда компилятор сталкивается с объектом в коде. Компилятор потирает руку и намеревается сделать объект A. При этом он увидит ,что у A есть член, который снова имеет тип A. Поэтому для завершения создания экземпляра A теперь он должен создать экземпляр другого A, и при этом он должен создать экземпляр другого A и так далее. Вы можете видеть, что это закончится рекурсией без привязки. Поэтому это недопустимо. Компилятор гарантирует, что он знает все типы и память требование всех членов, прежде чем он начнет создание экземпляра объекта класса.


простой способ понять причину класса A быть неполным-это попытаться взглянуть на него с точки зрения компилятора.

помимо прочего, компилятор должен иметь возможность вычислять размер