Здравствуйте, ArtDenis, Вы писали:
AD>Думаю, если ты даже не попытаешься максимально упросить код, который ещё воспроизводит проблему, а просто приведёшь полный текст ошибки, то найдутся те, кто догадается в чём проблема
Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'
Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.
=сначала спроси у GPT=
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, Shmj, Вы писали:
S>Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.
Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, Shmj, Вы писали:
S>Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'
S>Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.
C++ компилируется сверху вниз. На момент компиляции определённой строки он знает только то, что было написано выше. Поэтому — нет, не всё равно. В первом случае у тебя сначала идёт декларация — что есть такой-то конструктор, потом идёт ещё какой-то код (вероятно связанный с Class2), потом уже идёт реализация конструктора. И на момент компиляции этой реализации конструктора компилятор знает размер Class2. Во втором случае — это не так.
Помимо прочего: заголовочные файлы включаются в проект несколько раз (обычно). И если у тебя реализация метода в заголовочном файле, то компилятор будет её компилировать несколько раз. Само по себе это не ошибка, линкер всё разрулит, но это просто неправильная организация кода, увеличение времени компиляции. Единственная причина держать реализацию функции или метода в заголовочном файле это использование шаблонов.
Здравствуйте, Shmj, Вы писали:
S>Да какая тебе разница кто я? Причем тут переход на личности?
S>Потому что проблема не известна. Как раз и вопрос в том, что может вызывать такое поведение — хотя бы один вариант.
Просто возникают некоторые сомнения, в адекватности описания поведения. Особенно с учетом твоей личности
--
Справедливость выше закона. А человечность выше справедливости.
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, Videoman, Вы писали:
V>Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.
Вот еще бы минимальный пример...
=сначала спроси у GPT=
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, Videoman, Вы писали:
V>Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.
Гипотеза разумная. Но почему-то не работает:
Class1.h:
#include <memory>
class Class2;
class Class1
{
public:
Class1();
private:
std::unique_ptr<Class2> obj;
};
— по вашей гипотезе должно собираться, верно? Ведь раз взяло конструктор из файла Class1.cpp — то должно было бы увидеть и определение класса. Но не увидело — выдает ошибку.
=сначала спроси у GPT=
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
С дефолтным конструктором unique_ptr здесь проблем нет, т.к. там просто обнуление указателя на Class1, а для этого не нужно компилятору видеть полное определение Class1. Проблема должна быть с деструктором, т.к. там есть delete, а для работы delete нужно полное определение класса.
ЗЫ. Это ж классика PImpl-а, если мне склероз окончательно не изменил.
Хотя у меня не получилось повторить ситуацию, в которой, как я думал, компилятор будет ругаться. Поэтому прошу знатоков прокомментировать.
template <typename T>
class MyPtr {
T *ptr;
public:
MyPtr() {
ptr = new T();
}
};
class Class2;
class Class1 {
MyPtr<Class2> c2ptr;
Class1() {}
};
class Class2 { };
Я ожидал, что на строчке Class1(), где вызывается конструктор MyPtr, в свою очередь вызывающий конструктор Class2() программа не скомпилируется, т.к. на момент компиляции этой строки компилятор ещё не увидел полное объявление Class2 и не знает, есть ли у него публичный конструктор.
Однако же: компилируется. При этом если добавить классу Class2 приватный конструктор, то не компилируется, причём ошибка ссылается вперёд, туда, куда вроде как компилятор ещё не успел дойти.
Извиняюсь за дезинформацию, моё понимание С++ в данном случае подвело и я не знаю, почему так происходит.
Здравствуйте, rg45, Вы писали:
R>Ну и сколько еще подробностей придется из тебя вытащить, чтоб получить наконец полную картину?
rg45, зачем полная картина? И так же всё ясно: раз речь про конструктор, значит не удаётся создать поля класса. Значит в Class1 есть указатель (или иное использование) на Class2. А в Class2 есть указатель или иное использование Class1 — это не обязательно, но весьма вероятно. Поэтому перед/в Class1 есть фраза class Class2; — чтобы разорвать циклическую зависимость. Это означает что в Class1 Class2 не полный и когда конструктор пытаются определить прямо в Class1, то компилятор ругается, что не может создать то, что не описано. Более того, зная что Shmj новичок в С++, то можно утверждать с большой долей вероятности, что он не знает про циклические зависимости классов и способов их разрешения. Не знает про случаи, когда inline методы определяются вне класса и обычно в отдельном файле (а в некоторых случаях ещё и со своим расширением типа *.inc или *.inl (Ещё вариант — это добавление include после определение класса, но такое — экзотика)). Короче, ничего необычного, кроме сообщения об ошибке. Вот она меня удивила, так как не знал про static_assert(sizeof(_Tp)>0, в unique_ptr. Думал про массив нулевого размера. Видать этот static_assert нужен для предотвращения проблемы некорректного вызова деструктора для pimpl идиомы, но я этого не проверял.
И каждый день — без права на ошибку...
Re[10]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, B0FEE664, Вы писали:
BFE>rg45, зачем полная картина? И так же всё ясно: раз речь про конструктор, значит не удаётся создать поля класса. Значит в Class1 есть указатель (или иное использование) на Class2. А в Class2 есть указатель или иное использование Class1 — это не обязательно, но весьма вероятно. Поэтому перед/в Class1 есть фраза class Class2; — чтобы разорвать циклическую зависимость. Это означает что в Class1 Class2 не полный и когда конструктор пытаются определить прямо в Class1, то компилятор ругается, что не может создать то, что не описано. Более того, зная что Shmj новичок в С++, то можно утверждать с большой долей вероятности, что он не знает про циклические зависимости классов и способов их разрешения. Не знает про случаи, когда inline методы определяются вне класса и обычно в отдельном файле (а в некоторых случаях ещё и со своим расширением типа *.inc или *.inl (Ещё вариант — это добавление include после определение класса, но такое — экзотика)). Короче, ничего необычного, кроме сообщения об ошибке. Вот она меня удивила, так как не знал про static_assert(sizeof(_Tp)>0, в unique_ptr. Думал про массив нулевого размера. Видать этот static_assert нужен для предотвращения проблемы некорректного вызова деструктора для pimpl идиомы, но я этого не проверял.
Объяснение выглядит очень убедительным. Но я, признаться, даже не пытался вникать в суть "задачи", принимая во внимание персону и стиль задания вопросов.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, vsb, Вы писали:
vsb>Я ожидал, что на строчке Class1(), где вызывается конструктор MyPtr, в свою очередь вызывающий конструктор Class2() программа не скомпилируется, т.к. на момент компиляции этой строки компилятор ещё не увидел полное объявление Class2 и не знает, есть ли у него публичный конструктор. vsb>Однако же: компилируется. При этом если добавить классу Class2 приватный конструктор, то не компилируется, причём ошибка ссылается вперёд, туда, куда вроде как компилятор ещё не успел дойти. vsb>Извиняюсь за дезинформацию, моё понимание С++ в данном случае подвело и я не знаю, почему так происходит.
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation.
А там для зависимых имен кандидаты берутся из пространств имен, связанных с instantiation context.
Re[11]: Ошибка, если конструктор определен в h-файле (этюд?)
Здравствуйте, rg45, Вы писали:
R>Объяснение выглядит очень убедительным. Но я, признаться, даже не пытался вникать в суть "задачи", принимая во внимание персону и стиль задания вопросов.
А вот оно видите как — нужно смотреть на суть.
Вопрос то тянет на этюд — никто из "знатоков" так и не смог ответить. Возможно придется мне на выходных найти время и таки выцедить минимальный пример (надеюсь что нет).
=сначала спроси у GPT=
Re[12]: Ошибка, если конструктор определен в h-файле (этюд?)