170 похожих чатов

#Include <iostream> using std::cout; using std::cin; using std::endl; class A { public: virtual

~A() { cout << "Hello from A\n"; }
};

class B : virtual public A
{
public:
~B() override { cout << "Greeting from B\n"; }
};

class D : public B
{
public:
~D() override { cout << "Greeting from D\n"; }
};

int main()
{
A* d = new D;
delete d;
d = nullptr;
return 0;
}

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

65 ответов

181 просмотр

можно: не наследуйте D от базового класса

Sasha- Автор вопроса

ключевое слово НЕ виртуально, то есть мне нужно обычное наследование именно для D

Деструктор базового класса и так наследуется невиртуально.

Sasha
ключевое слово НЕ виртуально, то есть мне нужно об...

(прочиал UPD) вы хотите чтобы у объекта с динамическим типом D НЕ вызывался деструктор от типа D?

Sasha- Автор вопроса
Ilya Zviagin
Деструктор базового класса и так наследуется невир...

хорошо, давайте другой пример с Show #include <iostream> using std::cout; using std::cin; using std::endl; class A { public: virtual void Show() { cout << "Hello from A\n"; } }; class B : public A { public: void Show() override { cout << "Greeting from B\n"; } }; class D : public B { public: void Show() override { cout << "Greeting from D\n"; } }; int main() { A* d = new D; d->Show(); return 0; }

Sasha
хорошо, давайте другой пример с Show #include <io...

И ? Только быстрее, а то я спать уйду

Sasha- Автор вопроса
Sasha- Автор вопроса
Sasha
хочу чтобы вызвался Show из B

так, всё, пора спрашивать то, что я не люблю спрашивать: ЗАЧЕМ?

Sasha
хочу чтобы вызвался Show из B

Нет проблем! class D : public B { public: void Show() override { B::Show(); } };

Sasha- Автор вопроса
Ilya Zviagin
Что вызывалось ?

здесь метод Show виртуально унаследовался?

Ilya Zviagin
И ? Только быстрее, а то я спать уйду

хочу понаписать наследования с virtual'ами, но чтобы работало как без virtual'ов и без наследования

Sasha
здесь метод Show виртуально унаследовался?

Такого не бывает. Методы наслеюуются или нет, и бывают виртуальными или нет

Sasha- Автор вопроса
Ilya Zviagin
Такого не бывает. Методы наслеюуются или нет, и бы...

ну вот здесь он виртуально унаследовался, верно? у нас же есть указатель базового класса через который мы вызываем метод D

Sasha
здесь метод Show виртуально унаследовался?

Да, он в базовом объявлен виртуальным, будет везде виртуальным

Sasha
хочу чтобы вызвался Show из B

Я не очень понимаю в виртуальном этом всем, но думаю, для того что ты хочешь надо просто в классе D не определять метод show. (но я не уверен)

Sasha
ну вот здесь он виртуально унаследовался, верно? у...

Нельзя метод унаследовать виртуально или нет. Методы просто наследуются или нет, и могут быть виртуальными или нет.

Ilya Zviagin
Нельзя метод унаследовать виртуально или нет. Мето...

тут явно заявка на пропозал на киллерфичу для C++29

Sasha
ну вот здесь он виртуально унаследовался, верно? у...

Он ВЫЗЫВАЕТСЯ виртуально, а не наследуется.

Ilya Zviagin
Нельзя метод унаследовать виртуально или нет. Мето...

Не совсем понял твои слова "метод наследуется ИЛИ нет". Я всегда думал, что если в базовом классе есть какой то метод, то в производном он будет по любому. Он всегда наследуется. Другое дело, что если он виртуальный, то ты можешь его переопределить в производном. Или все таки можно как то сделать так, чтоб метод базового вообще по попадал в состав производного? Мне кажется так нельзя

Sasha- Автор вопроса
Ilya Zviagin
Он ВЫЗЫВАЕТСЯ виртуально, а не наследуется.

ну вот есть class A { public: virtual Show(); } здесь этот метод Show будет ко всей цепочке унаследованных классов являться virtual?

Понял. Но тогда его можно будет вызвать только через указатель на производный (через базовый нельзя) верно я понимаю?

Sasha- Автор вопроса
Ilya Zviagin
Да. По другому не бывает

ещё раз переспрошу для уверенности, то есть class A { public: virtual void Show(); }; class B : public A { public: void Show(); }; class C : public B { public: void Show(): }; здесь метод Show в классе C никак обычно не унаследовать UPD: чтобы при вызове A* c = new C; c.Show(); вызвался метод класса B, но не C. Просто есть цепочка A->B->C, если метод Show класса С можно как то унаследовать обычно, то тогда по логике должно вызваться Show метода B )))

The Pressbraker
Не совсем понял твои слова "метод наследуется ИЛИ ...

Ну и приватные функции функционально (не технически) не наследуются по понятным причинам.

наследуются

Ilya Zviagin
наследуются

Только технически. Использовать это никак не получится (по крайней мере без очень грязных хаков).

Sasha- Автор вопроса

апдейтнул

Alexander "Ternvein" Isaev
Только технически. Использовать это никак не получ...

Ну тебе компилятор при вызове будет говорить, что метод недоступен. Вот если его ПЕРЕГРУЗИТЬ в наследнике, он скроется.

Sasha
ещё раз переспрошу для уверенности, то есть class...

Я писал выше. Переопределить в C метод Show() и вызвать в нём метод класса B (B::Show). НО c деструкторами такой финт не прокатит, 0) деструктор всегда есть и 1) он всегда будет вызван, 2) и потом будет вызван деструктор базового класса.

Alexander "Ternvein" Isaev
Только технически. Использовать это никак не получ...

https://en.cppreference.com/w/cpp/memory/memory_resource (обратите внимание на приватные виртуалы)

Гражданин Котейко
https://en.cppreference.com/w/cpp/memory/memory_re...

Я знаю эту шляпу, но не одобряю. Они должны быть protected.

Alexander "Ternvein" Isaev
Я знаю эту шляпу, но не одобряю. Они должны быть p...

не, не должны, по исходной задумке их только база из невиртуального интерфейса дёргает

Sasha- Автор вопроса
Ilya Zviagin
Деструктор базового класса и так наследуется невир...

да, но только, если будет вызван через свой же указатель, а не через базовый. Потому что если через базовый, то только базовый деструктор и вызовется

Sasha
да, но только, если будет вызван через свой же ука...

Все так: как и для любого другого невиртуального метода. В отличие от них, впрочем, деструктор производного класса, в случае если базовый объявлен виртуальным, не заменит, а дополнит порядок разрушения объекта. Т.е.: struct B { virtual void f ( ); virtual ~B ( ); }; struct D: B { void f ( ) override; ~D ( ) override; }; int main ( ) { B* b{new D}; b->f() /* #1 */; delete b /* #2 */; } В #1 вызовется D::f(), но в #2 вызовется D::~D(), после чего B::~B().

Sasha- Автор вопроса
Sasha- Автор вопроса
Sergey Anisimov
Все так: как и для любого другого невиртуального м...

это да, а если ну будет виртуального наследования, то вызовется в этом случае только деструктор структуры B

Sasha
что это за конструкция {new D}?

Скорее b{}: это один из синтаксисов инициализации. В разных ситуациях (не)возможно использование в этих целях =, () или {} (как здесь). new D - выражение, создающее объект типа D с dynamic-storage-duration (объект, управление временем жизни которого осуществляется вручную и может производиться во время выполнения).

Sasha
это да, а если ну будет виртуального наследования,...

Если точнее, в этом случае будет неопределенное поведение (программа содержит недиагностируемую фатальную ошибку, последствия (даже неизбежного достижения в будущем которой) которой формально непредсказуемы).

Sasha- Автор вопроса
Sasha
у меня твой код не комплится)

Скорее всего потому, что под "не компилится" Вы понимаете "не компонуется": он и не может, поскольку определения для всех используемых функций в примере отсутствуют (они для него не нужны). Если хотите его собрать - замените все точки с запятыми в пределах определений структур на пары фигурных скобок.

Sasha- Автор вопроса
Sasha- Автор вопроса
Sergey Anisimov
Скорее всего потому, что под "не компилится" Вы по...

а с чего вы взяли, что это компоновка а не компиляция? я так почитал, что такое компоновка и как для себя понял, компилятор сначала преобразует всё в машинный код, затем в обьекты, а компоновкщик обьединяет это всё

Sasha
а с чего вы взяли, что это компоновка а не компиля...

Компилятор работает в пределах контекста единицы трансляции. Он как раз свою работу способен выполнять и без доступа к определениям функций в том примере.

Sergey Anisimov
Все так: как и для любого другого невиртуального м...

Ребят, не могли бы Вы поделиться источниками по которым Вы изучали ООП? Всё что я видел либо поверхностное, либо не разбирает подобных махинаций

Pasha Kryvulets
Ребят, не могли бы Вы поделиться источниками по ко...

Непосредственно к ООП это отношения не имеет; это про работу языка. Помимо каких-то преимущественно базовых представлений, конкретно я свои отсюда и отсюда получал. Первое - справочник по языку, второе - актуальный черновик спецификация языка. Насколько такой подход можно рекомендовать - не подскажу.

Sasha
что это за конструкция {new D}?

uniform инициализация адресом, который возвращает оператор new.

Sasha- Автор вопроса

а в чем её прикол, или это просто как фишка?

Sasha
а в чем её прикол, или это просто как фишка?

Как по мне, это универсальный способ инициализации и присваивания переменных, массивов и объектов.

Pasha Kryvulets
Ребят, не могли бы Вы поделиться источниками по ко...

Да разбирает. Просто надо вдумываться. В лбом учебнике по с++ это есть, Липпман например, или Детей Детей.

Sasha
ключевое слово НЕ виртуально, то есть мне нужно об...

Ты не можешь проигнорировать и обойти деструктор базового класса. Он все равно будет выполнен.

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Он в одиночку это дело запилил или была какая-то команда?
Aquinary
12
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Oh sorry did you want it in Gunter's chains?
Martin Rys
15
Всем привет, нужна как никогда, нужна помощь с IO в загрузчике. Пишу в code16 после установки сегментных регистров, пишу вывод символа. Пробовал 2 варианта: # 1 mov $0x0E, %a...
Shadow Akira
14
Подскажите пожалуйста, как в CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); получить наз...
A Z
7
Раз начали говорить про embassy, то присоединюсь со своими парой вопросов. 1) Есть ли сопоставимые аналоги для асинхронного кода в emdebbed? 2) Можно ли внутри задач embassy ...
NI_isx
4
Карта сайта