+3
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
#include <iostream>
using namespace std;
class Base {
public:
Base() {
cout << "Base construct\n";
}
virtual ~Base() {
cout << "Base destruct\n";
}
};
class Child: public Base {
public:
Child() {
cout << "Child construct\n";
}
~Child() {
cout << "Child destruct\n";
}
};
int main() {
Base *base = new Child();
delete base;
}
Hy нe oчeвиднo жe! Для тoгo, чтoб вызывaлиcь вce дecтpyктopы, нyжнo oбъявить eгo виpтyaльным. B тo вpeмя кaк кoнcтpyктop бeз мoдификaтopa virtual paбoтaeт тaк жe, кaк виpтyaльный дecтpyктop.
И зaчeм вoбщe ocтaвлять вoзмoжнocть нe виpтyaльнoгo дecтpyктopa - нe мoгy пpeдcтaвить ceбe cлyчaя, кoгдa пpи yдaлeнии oбъeктa нyжeн вызoв дecтpyктopa тoлькo бaзoвoгo клacca.
Запостил:
Pythoner,
18 Марта 2014
Т.е. ты не можешь представить себе случай, когда класс не подразумевает наличия наследников? У меня 96.8% классов таких.
а теперь перечитай ещё раз мой комментарий
Причем тут класс без наследников?
Если у класса не должно быть наследников, зачем ему может понадобиться виртуальный деструктор?
Правильно, не нужен.
new Derived - какой вызвал, такой и вызвался
> Схуялли он ведёт себя как виртуальный?
1. Наблюдатель удаляет объект хрен знает какого класса, имея указатель на объект класса родителя - вызывается только деструктор родителя.
2. Наблюдатель добавляет слово virtual к деструктору - вызываются деструкторы [b]потомков[b] и деструктор родителя.
3. Наблюдатель делает вывод: "виртуальный %X%", при вызове которого вызывается не только %X% потомка, но и %X% родителя.
4. Наблюдатель создаёт объект - вызываются конструктор родителя и конструкторы потомков.
5. С точки зрения наблюдателя конструктор - виртуальный.
UPD: Тьфу, автор уже описал этот мысленный эксперимент, но менее подробно в http://govnokod.ru/15517#comment221649. И я же читал тот комментарий...
Что будет плохого, если объявить все деструкторы виртуальными, а там, где на стадии компиляции ясно, какой класс, не лезть в таблицу и вызывать сразу нужные деструкторы?
Ну и это нарушает один из основопологающих принципов плюсов - не платить за то, что не используешь.
> там, где на стадии компиляции ясно, какой класс, не лезть в таблицу и вызывать сразу нужные деструкторы?
Это оптимизация уже давно работает для всех виртуальных функций (и деструкторов). Если компилятору точно известен тип, виртуальные функции вызываются невиртуально.
Не подумал об этом. А для оптимизации (удаления лишнего поля) уже потребуется перекомпилировать класс-родитель, печаль.
А для динамического полиморфизма подойдёт сахар-динамитор, что-то типа более удобного tagged union.
В теории можно было сказать "пусть деструктор будет виртуальным только у типов, объявленных с ключевым словом class", но это уже попахивает Д.
Да и лейаут оно не испортит, если не забывать каст (который в данном случае уже не nop).
Опять же, как отличить структуру, от которой мы хотим иметь возможность наследоваться, от старой доброй сишной? Если POD - нет виртуального деструктора, если не POD - есть?
Я за явный virtual для деструктора, explicit is better than implicit. В крестах и так слишком много сложностей на ровном месте.
Слово struct оставить для POD'ов, полностью запретив в них виртуальные методы, динамик каст, множественное наследование и наследование от не POD'ов.
Слово class оставить для настоящих классов, у которых виртуальный деструктор и ТВМ никак не убираются. И запретить наследовать class от struct, ибо нехрен.
> добавить к стуктурке удобных методов, не потеряв возможности запихивать её в старые функции.
Вполне так решается агрегацией:
меня бесит, что по умолчанию в class всё private, неудобно же
О да, "public:" писать же так дооолго... В жабе вон вообще почти к каждому полю или методу пишут, и ничего, живые.
> руки прочь от struct!
Да никто никогда его не тронет :) Совместимость же.
учитывая, что обычно класс/структура описывается в таком порядке, что сначала идут публичные поля, а в подвале - приватные
Да ну, я и так всегда пишу class и public: для не POD'ов... Как-то не напрягает. Юзать struct чисто ради дефолтного паблика на верхнюю половину класса, имхо, как-то не айс...
Убрать дефолтный private/public вообще, чтобы положить конец битве остроконечников с тупоконечниками. Пусть пишут явно в обоих случаях.
Вам в D. Который, правда, всё равно не взлетит, т.к. самое важное в нём явно скоро доперетащат в кресты...
Угу. Останется в недрах лицакниги при поддержке Александреску.
Судя по всему что-то совсем небольшое и простенькое. Или D настолько компактней c++, что в такой объем войдет что-то серьезное?
На первый взгляд он максимум в 1,5-2 раза компактней. Проверять, написав что-то нетривиальное на том и на другом желания никакого, как и вообще писать что-то на D.
Цитирую одного из разработчиков D1:
Now using Eclipse + C Dev Tools (CDT) and GCC as the IDE and tool-chain respectively, I feel I'm back to really cooking on gas once again.
"Oh C++, why did I ever leave you?"
Да это всё понятно. И на сайте d написано, что как и с чем можно линковать.
P.S. книжка александреску вышла в том же году :)
шарпопуть
зря, динамитор таки нужен
Или я не так понял твою идею?
И после динамирования они становятся неподами.
И в 146% из них вообще не написаны деструкторы, т.к. дефолтная реализация вполне устраивает ;)
Это полный бред. При конструировании компилятор точно знает, какой тип конструируется, и может правильно сгенерировать код инициализации. Деструктор же может вызваться непонятно где на объекте неизвестного компилятору класса (есть только указатель на базу), компилятор не может правильно уничтожить иерархию без поддержки рантайма.
Если не уничтожать объекты по указателям на базу (например, всегда аллоцировать их на стеке), механизмы конструирования и деконструкции корректны и симметричны.
Более того, в крестах конструктор не бывает виртуальным хихи
1) Если не объявить деструктор виртуальным, вызовется деструктор только базового класса.
2) Есои обьявить его виртуальным, последовательновызовуться все леструкторы предков этого класса.
3) Конструктор работает так же, как виртуальный леструктор - вызываются все конструкторы предков.
Вопрос: нафига козе баян - нафиг описывать деструктор как virtual, если по другому и не над чтоб он работал?пс пишу с тела, сори за ошибки.
Правда чтоли?
GCC 4.8.1, там как раз всё по стандарту. Аналогичный результат был бы на Borland C++ девяностых годов.
> вызывается только деструктор Base
Может всё же попробовать понять разницу между разрушением объекта известного типа и удалением указателя на базовый класс?
завидую твоему свободному времени
P.S. Да и Тарас с Романом вполне справляются ;)
Я в том районе совсем недолго был - поднялся со стороны озера с гидрой, увидел что-то похожее на ходячий гриб, хотел разглядеть поближе, и тут из-за деревьев выбежал большой кошак...
Так что с грибами пообщаться пока не довелось.
https://www.youtube.com/watch?v=jWkPpTv1vXk
P.S. Волка жалко ;(
http://ideone.com/zGxwzm
http://ideone.com/7SRoRr
за логические?