Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826

Default деструктор и forward declaration

30.08.2021, 14:07. Показов 2121. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, подскажите пожалуйста почему компилятор выдает ошибку при использовании default в header файле с forward классом.

C++
1
2
3
4
5
6
7
8
9
//.h
class ForwardClass;
 
class Test
{
    std::unique_ptr<ForwardClass> ptr;
    Test();
    virtual ~Test() = default;
}
Можно ли как-то обойти вынос default в cpp файл в данном случаи?
Ошибка на компиляторах Mac, на gcc пропускает такое
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.08.2021, 14:07
Ответы с готовыми решениями:

Forward declaration
#ifndef __PROGTEST__ #include много инклудов using namespace std; #endif /* __PROGTEST__ */ template &lt;typename _T, typename...

Forward declaration
Привет! Есть два класса, один создаёт другой и передаёт в него ссылку на самого себя, чтобы тот мог вызывать некоторые функции первого....

Forward declaration и рекурсивный include
В обоих классах нужно использовать поля друг друга, при таком подходе: //Ship.h #include &quot;Player.h&quot;//Player.h -...

10
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.08.2021, 14:21
rikimaru2013, delete для указателя на неполный тип - UB.
Деструктор по умолчанию ~Test генерирует вызов деструктора ~std::unique_ptr<ForwardClass>, который содержит delete для неполного ForwardClass.

Сам по себе вынос в cpp эту ситуацию не решит. Цель именно в том, чтобы в точке, где появляется определение ~std::unique_ptr<ForwardClass> тип ForwardClass был полным. Если в cpp ForwardClass - полный тип, значит надо выносить туда.

Добавлено через 1 минуту
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
gcc пропускает такое
Это ни о чем не говорит. Ошибка все равно есть.
2
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
30.08.2021, 20:48
Цитата Сообщение от DrOffset Посмотреть сообщение
Цель именно в том, чтобы в точке, где появляется определение ~std::unique_ptr<ForwardClass> тип ForwardClass был полным.
Не роясь в тексте стандарта, мне навскидку припоминается, что формальной "точкой определения" такого деструктора будет самый конец единицы трансляции. (Возможно, я ошибаюсь и это относится к чему-то другому.)

То есть для того, чтобы код скомпилировался, не обязательно предоставлять полное определение ForwardClass именно выше по коду. Достаточно предоставить его где угодно в каждой единице трансляции, включающей определение Test. Если это так, то переносить = default определение деструктора никуда не нужно.

GCC и Clang ведут себя именно так. Интересно, это стандартное поведение или это их самодеятельность?

---

Или скорее слова "implicitly defined when it is odr-used" отсюда

A destructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) or when it is explicitly defaulted after its first declaration.
следует понимать так, что точкой определения для такого деструктора является точка его первого использования (а не конец единицы трансляции). Тогда, опять же, GCC и Clang правы, что не выдают ошибку сразу на определение класса Test.

Но GCC, Clang и MSVC++ компилируют и такое

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <memory>
 
class ForwardClass;
 
class Test
{
    std::unique_ptr<ForwardClass> ptr;
public:    
    Test() = default;
    virtual ~Test() = default;
};
 
int main()
{
  Test t;
}
 
class ForwardClass
{
};
Должно это компилироваться или нет?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.08.2021, 20:55
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Должно это компилироваться или нет?
Я подумал над вашим замечанием и мне кажется, что должно.
По той же причине, что должен компилироваться такой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void foo();
 
inline void boo()
{
    foo();
}
 
int main()
{
    boo();
}
 
inline void foo()
{
   //.....
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
30.08.2021, 21:26
Цитата Сообщение от DrOffset Посмотреть сообщение
По той же причине, что должен компилироваться такой код:
Мне кажется, что здесь скорее играет роль вот это в применении к деструктору std::unique_ptr<ForwardClass> (С++17)

17.6.4.1 Point of instantiation
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. [...]
Это именно то, что я имел в виду выше под "навскидку припоминается".

Добавлено через 6 минут
То есть по идее вот такой пример тоже должен компилироваться

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ForwardClass;
 
template <typename T> void foo()
{
  ForwardClass f;
}
 
int main()
{
  foo<int>();
}
 
class ForwardClass
{
};
несмотря на то, что ни в точке определения шаблона класс не является полным, ни в точке вызова (инстанцирования) foo<int>() класс не является полным.
2
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
30.08.2021, 21:48
TheCalligrapher, думаю, в случае ТС'а имеется не одна единица трансляции. В таком случае и gcc не будет собирать подобный код, если явно не определить деструктор в единице трансляции, в которой доступно определение класса.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
30.08.2021, 22:15
Цитата Сообщение от Croessmah Посмотреть сообщение
думаю, в случае ТС'а имеется не одна единица трансляции. В таком случае и gcc не будет собирать подобный код, если явно не определить деструктор в единице трансляции, в которой доступно определение класса.
Да, но в GCC вот такой код компилируется

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <memory>
 
class ForwardClass;
 
class Test
{
    std::unique_ptr<ForwardClass> ptr;
public:    
    Test() = default;
    virtual ~Test() = default;
};
 
int main()
{
}
То есть похоже, что GCC в такой ситуации не генерирует деструктор для Test, несмотря на его виртуальность, и не тянет за ним всю цепочку зависимых инстанцирований. То есть все еще зависит от того, что там происходит у ТС в этих единицах трансляции.
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
31.08.2021, 08:46
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
То есть по идее вот такой пример тоже должен компилироваться
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ForwardClass;
 
template <typename T> void foo()
{
  ForwardClass f;
}
 
int main()
{
  foo<int>();
}
 
class ForwardClass
{
};
Ill-formed, no diagnostic required.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
31.08.2021, 09:44
Цитата Сообщение от argcargv Посмотреть сообщение
Ill-formed, no diagnostic required.
Логично. Но цитата/ссылка required
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
31.08.2021, 10:51
TheCalligrapher, https://timsong-cpp.github.io/... mp.res#8.3

Добавлено через 1 час 4 минуты
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
A destructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) to destroy an object of its class type or when it is explicitly defaulted after its first declaration.
Это было изменено в CWG2068, статус поддержки которого в GCC и Clang Unknown.
3
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
01.09.2021, 01:43
Ага, понял. Спасибо.

Также, если поднять определение класса чуть выше, будет еще применимо: https://timsong-cpp.github.io/... .res#8.4.1

То есть мое исходное предположение (#5) о том, что поведение компиляторов объясняется 17.6.4.1/8 - верное. Это точка инстанцирования в конце файла была добавлена здесь:

http://www.open-std.org/jtc1/s... s.html#993

и добавлена специально для того, чтобы дать компиляторам свободу просто ни о чем не беспокоясь инстанцировать все шаблоны в конце файла. Что они и делают.

Но при этом требуется, чтобы из всех точек инстанцирования, реальных и гипотетических, шаблон имел одну и ту же интерпретацию. В противном случае: ill-formed, no diagnostic required.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.09.2021, 01:43
Помогаю со студенческими работами здесь

Precompiled headers, STL forward declaration
Та да :) Хотел уточнить кое - чего по прекомпайлам. Вот есть у меня файл stdafx.h для прекомпайл хедеров: #pragma once ...

Почему иногда не могу использовать forward declaration
Почему иногда не могу использовать forward declaration? Т.к. сразу вылезает масса ошибок и приходится подключать как хейдер. А иногда всё...

Enum forward declaration - как достать базовый тип?
Доброго времени суток. Есть *.h файл, в котором нужно сделать forward declaration enum (не enum class). Первое что приходит в...

Ошибка компилятора, неверное выравнивание при forward declaration
Уже не первый раз сталкиваюсь с ошибкой когда, одна и та же структура имеет разный вес в разных частях программы (по разному выравнивается)...

Unsatisfied forward or external declaration
Unsatisfied forward or external declaration - что это значит? процедуры у меня обьявлены в Type, описание их тоже есть, как поправить?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru