"Неполный тип" в классе, который имеет член того же типа самого класса
У меня есть класс, который должен иметь отдельный член того же класса, что-то вроде:
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
быть неполным-это попытаться взглянуть на него с точки зрения компилятора.
помимо прочего, компилятор должен иметь возможность вычислять размер