Re[2]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 11:56
Оценка: -1 :)
Здравствуйте, ArtDenis, Вы писали:

AD>Думаю, если ты даже не попытаешься максимально упросить код, который ещё воспроизводит проблему, а просто приведёшь полный текст ошибки, то найдутся те, кто догадается в чём проблема


Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'

Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.
=сначала спроси у GPT=
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: serg_joker Украина  
Дата: 05.07.23 12:09
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Подождем, может еще кто знает.

Ну я знаю. Но тебе ничего доказывать не буду.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Videoman Россия https://hts.tv/
Дата: 05.07.23 13:06
Оценка: 1 (1) +1
Здравствуйте, Shmj, Вы писали:

S>Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.


Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: vsb Казахстан  
Дата: 05.07.23 13:17
Оценка: 1 (1) +1
Здравствуйте, Shmj, Вы писали:

S>Текст ошибки: invalid application of 'sizeof' to an incomplete type 'namespace1::Class2'


S>Но мой вопрос в другом — не нужно именно такую же ошибку. Вообще почему может возникать — не все ли равно компилятору где определен ПУСТОЙ конструктор??? Любое доказательство что компилятору не все равно — меня устроит.


C++ компилируется сверху вниз. На момент компиляции определённой строки он знает только то, что было написано выше. Поэтому — нет, не всё равно. В первом случае у тебя сначала идёт декларация — что есть такой-то конструктор, потом идёт ещё какой-то код (вероятно связанный с Class2), потом уже идёт реализация конструктора. И на момент компиляции этой реализации конструктора компилятор знает размер Class2. Во втором случае — это не так.

Помимо прочего: заголовочные файлы включаются в проект несколько раз (обычно). И если у тебя реализация метода в заголовочном файле, то компилятор будет её компилировать несколько раз. Само по себе это не ошибка, линкер всё разрулит, но это просто неправильная организация кода, увеличение времени компиляции. Единственная причина держать реализацию функции или метода в заголовочном файле это использование шаблонов.
Отредактировано 05.07.2023 13:18 vsb . Предыдущая версия .
Re[3]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 13:25
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Да какая тебе разница кто я? Причем тут переход на личности?


S>Потому что проблема не известна. Как раз и вопрос в том, что может вызывать такое поведение — хотя бы один вариант.


Просто возникают некоторые сомнения, в адекватности описания поведения. Особенно с учетом твоей личности
--
Справедливость выше закона. А человечность выше справедливости.
Re[8]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 13:28
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Совершенно верно — unique_ptr<Class2> внутри есть.


Ну и сколько еще подробностей придется из тебя вытащить, чтоб получить наконец полную картину?
--
Справедливость выше закона. А человечность выше справедливости.
Re[9]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 13:31
Оценка: :)))
Здравствуйте, rg45, Вы писали:

R>Ну и сколько еще подробностей придется из тебя вытащить, чтоб получить наконец полную картину?


Мне не нужно знать в чем проблема была именно в том частном случае.

Мне нужно понимание почему вообще перенос пустого конструктора в H-файл может приводить к ошибке компиляции — какая разница компилятору?
=сначала спроси у GPT=
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 13:36
Оценка: :)))
Здравствуйте, Videoman, Вы писали:

V>Ему естественно не всё равно. Пустой конструктор в месте своего объявления также создает пустые конструкторы вех членов класса. Может быть ситуация, когда в .h есть только декларация члена класса, но нет определения, а в .cpp определение уже есть полностью. Обычно таким свойством обладают шаблонные классы параметризуемые типами не требующими определения до момента конструирования. Например конструктор std::unique_ptr<> по умолчанию может потребовать delete-r (и соответственно определение класса, его деструктор в частности) в месте определения конструктора родителя.


Вот еще бы минимальный пример...
=сначала спроси у GPT=
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 13:38
Оценка: +1 :)
Здравствуйте, Shmj, Вы писали:

S>Пока вы не доказали что способны решить эту задачу.


Просто непревзойденная наглость.
--
Справедливость выше закона. А человечность выше справедливости.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Videoman Россия https://hts.tv/
Дата: 05.07.23 13:52
Оценка: +2
Здравствуйте, Shmj, Вы писали:

S>Вот еще бы минимальный пример...

// .h

class class1;

class class2 {

  class2();

  std::unique_ptr<class1> ptr;
}

// .cpp

#include "class1.h"

class2::class2()
{
}

Как-то так, но я не компилировал.
Re[4]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 13:55
Оценка:
Здравствуйте, 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
#include "Class1.h"

class Class2
{
};


Class1::Class1()
{

}


— по вашей гипотезе должно собираться, верно? Ведь раз взяло конструктор из файла Class1.cpp — то должно было бы увидеть и определение класса. Но не увидело — выдает ошибку.
=сначала спроси у GPT=
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 14:01
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Как-то так, но я не компилировал.


Сделал так:

Class1.h
#include <memory>

class Class2;

class Class1
{
public:
    Class1();
private:
    std::unique_ptr<Class2> ptr;
};


Class1.cpp
#include "Class1.h"
#include "Class2.h"

Class1::Class1()
{
}


Class2.h
class Class2
{
};


— не компилируется. unique_ptr хочет заранее знать какой класс даже в этом случае, не смотря на то, что конструктор только декларирован — ему пофиг.
=сначала спроси у GPT=
Re[6]: Ошибка, если конструктор определен в h-файле (этюд?)
От: so5team https://stiffstream.com
Дата: 05.07.23 14:11
Оценка:
Здравствуйте, Videoman, Вы писали:

V>
V>// .h

V>class class1;

V>class class2 {

V>  class2();

V>  std::unique_ptr<class1> ptr;
V>}

V>// .cpp

V>#include "class1.h"

V>class2::class2()
V>{
V>}
V>

V>Как-то так, но я не компилировал.

С дефолтным конструктором unique_ptr здесь проблем нет, т.к. там просто обнуление указателя на Class1, а для этого не нужно компилятору видеть полное определение Class1. Проблема должна быть с деструктором, т.к. там есть delete, а для работы delete нужно полное определение класса.

ЗЫ. Это ж классика PImpl-а, если мне склероз окончательно не изменил.

ЗЗЫ. У ТС-а, скорее всего, что-то такое:

// .h
class Class2;

class Class1 {
  std::unique_ptr<Class2> ptr_member_{new Class2{}};
  ...
public:
  Class1();
  ~Class1();
  ...
};

// .cpp
class Class2 {...}

Class1::Class1() {}
Class1::~Class1() {}


В этом случае, если не путаю, перенос конструктора Class1 из .cpp в .h и должен привести к ошибке компиляции.
Re[5]: Ошибка, если конструктор определен в h-файле (этюд?)
От: vsb Казахстан  
Дата: 05.07.23 14:16
Оценка: 4 (1)
Хотя у меня не получилось повторить ситуацию, в которой, как я думал, компилятор будет ругаться. Поэтому прошу знатоков прокомментировать.

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 приватный конструктор, то не компилируется, причём ошибка ссылается вперёд, туда, куда вроде как компилятор ещё не успел дойти.

Извиняюсь за дезинформацию, моё понимание С++ в данном случае подвело и я не знаю, почему так происходит.
Отредактировано 05.07.2023 14:18 vsb . Предыдущая версия .
Re[7]: Ошибка, если конструктор определен в h-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 14:22
Оценка:
Здравствуйте, so5t

S>В этом случае, если не путаю, перенос конструктора Class1 из .cpp в .h и должен привести к ошибке компиляции.


Даже ваш вариант не компилируется — без переноса конструктора — use of undefined type 'Class2'
=сначала спроси у GPT=
Re[9]: Ошибка, если конструктор определен в h-файле (этюд?)
От: B0FEE664  
Дата: 05.07.23 14:25
Оценка: +2
Здравствуйте, 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-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 15:01
Оценка: +1
Здравствуйте, 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-файле (этюд?)
От: andrey.desman  
Дата: 05.07.23 16:19
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Я ожидал, что на строчке Class1(), где вызывается конструктор MyPtr, в свою очередь вызывающий конструктор Class2() программа не скомпилируется, т.к. на момент компиляции этой строки компилятор ещё не увидел полное объявление Class2 и не знает, есть ли у него публичный конструктор.

vsb>Однако же: компилируется. При этом если добавить классу Class2 приватный конструктор, то не компилируется, причём ошибка ссылается вперёд, туда, куда вроде как компилятор ещё не успел дойти.
vsb>Извиняюсь за дезинформацию, моё понимание С++ в данном случае подвело и я не знаю, почему так происходит.

Как минимум

https://timsong-cpp.github.io/cppwp/n4659/temp.dep.res#temp.point-8

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-файле (этюд?)
От: Shmj Ниоткуда  
Дата: 05.07.23 18:22
Оценка: :))) :))) :)))
Здравствуйте, rg45, Вы писали:

R>Объяснение выглядит очень убедительным. Но я, признаться, даже не пытался вникать в суть "задачи", принимая во внимание персону и стиль задания вопросов.


А вот оно видите как — нужно смотреть на суть.

Вопрос то тянет на этюд — никто из "знатоков" так и не смог ответить. Возможно придется мне на выходных найти время и таки выцедить минимальный пример (надеюсь что нет).
=сначала спроси у GPT=
Re[12]: Ошибка, если конструктор определен в h-файле (этюд?)
От: rg45 СССР  
Дата: 05.07.23 18:25
Оценка: +3 :)
Здравствуйте, Shmj, Вы писали:

S>А вот оно видите как — нужно смотреть на суть.


На твою суть я тут уже насмотрелся предостаточно.
--
Справедливость выше закона. А человечность выше справедливости.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.