Форум программистов, компьютерный форум CyberForum.ru

Наследование. Виртуальные методы/деструкторы. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.85
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
28.04.2012, 12:33     Наследование. Виртуальные методы/деструкторы. #1
Есть базовый класс Cell (код можно даже не смотреть - он просто для иллюстрации -> вопрос внизу)
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Cell
{
    friend class Obstacle; 
    friend class Prey;
    friend class Predator;
    
    Ocean *ocean;
    int line;
    int column;
 
public:
    Cell(int, int );
 
    virtual void exec() = 0;
    void print();
 
    virtual ~Cell(); //по слову виртуал - ВОПРОС
};
P.s. Класс Ocean - в данном вопросе не важен.

в его(Cell) френдах сидят его же наследники:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Obstacle : public Cell
{
    
public: 
    Obstacle(int,int);
 
    void exec();
    void print();
 
    ~Obstacle();
};
 
 
class Prey : public Cell
{
public:
    Prey(int,int);
    
    void exec();
    void print();
 
    ~Prey();
};
 
class Predator : public Prey
{
public: 
    Predator(int,int);
 
    void exec();
    void print();
 
    ~Predator();
};
Ну теперь к вопросу: в базовом классе Cell есть виртуальный метод. Правило хорошего тона советует: "если в классе есть хотя бы один виртуальный метод - сделай виртуальный деструктор". Предположим, что при вызове деструктора Cell мне нужно будет сделать
C++ (Qt)
1
delete ocean;
Тогда:
если я опишу НЕвиртуальный деструктор, то в классах Prey и Obstacle, которые напрямую наслудуются от Cell этот деструктор будет вызываться -> то есть память под ocean - будет успешно удалена. НО! я отрыл, что, если наследовать от класса с виртуальными методами, то у потомка автоматически генерируется виртуальный деструктор, то есть для класса Predator мне придётся заного писать деструктор, который удаляет память под ocean?! или я чего-то не так понял?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.04.2012, 12:33     Наследование. Виртуальные методы/деструкторы.
Посмотрите здесь:

наследование и виртуальные ф-ии C++
Наследование и виртуальные методы C++
Ромбовидное наследование. Деструкторы. C++
C++ Классы, конструкторы, деструкторы, методы классов
Виртуальные деструкторы C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
28.04.2012, 17:41     Наследование. Виртуальные методы/деструкторы. #2
Не так. При уничтожении автоматических объектов всё обрабатывается правильно в любом случае, а вот если мы сделаем так:
C++
1
2
3
4
5
6
void foo()
{
    Cell *ptr = new Prey();
    // ...
    delete ptr;
}
то при невиртуальном деструкторе будет вызван деструктор именно от Cell, а не от Prey, что в корне неправильно. Если же в Cell деструктор виртуальный, то будет вызван деструктор Prey, который автоматически обратится и к деструктору Cell.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
28.04.2012, 19:57  [ТС]     Наследование. Виртуальные методы/деструкторы. #3
Ваш пример мне понятен
не понял фразу "При уничтожении автоматических объектов всё обрабатывается правильно в любом случае". может быть в ней и кроется ответ на мой вопрос)) но, на всякий случай, попробую его по-лучше сформулировать:
в Cell есть указатель на Ocean. Предположим, что мне (неважно зачем - просто пример) в деструкторе Cell нужно сделать
C++ (Qt)
1
delete ocean;
Далее я я рассуждаю так:
1.) если деструктор Cell был НЕвиртуальным, то деструкторы производных классов (Obstacle и Prey) вызовут деструктор базового класса (то есть Cell) и пресловутый океан будет удалён
2.) если деструктор Cell был виртуальным, то деструкторы производных классов (Obstacle и Prey) заменят деструктор класса Cell, то есть океан окажется неудалённым - значит эту строку
C++ (Qt)
1
delete ocean;
придётся повторно написать в деструкторах производных классах.
Если следовать этой логике, то
3.) деструктор Predator - потомка Prey заменит собой деструктор Prey - то есть в Predator опять же нужно будет удалять океан...

Объясните, в чём я не прав...
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
28.04.2012, 20:10     Наследование. Виртуальные методы/деструкторы. #4
Цитата Сообщение от IcyWind Посмотреть сообщение
2.) если деструктор Cell был виртуальным, то деструкторы производных классов (Obstacle и Prey) заменят деструктор класса Cell, то есть океан окажется неудалённым - значит эту строку
Нет, не заменят, все деструкторы так же будут вызваны по цепочке, от производного класса к базовому. Виртуальный деструктор нужен для того, что бы корректно удалять производный класс по указателю на базовый. Например, есть код:
C++
1
2
3
Cell * cell = new Obstacle();
// ...
delete cell;
Если деструтор Cell - не виртуальный, то будет вызван только он. Если виртуальный, то сначала будет вызван деструктор Obstacle, затем деструктор Cell.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
28.04.2012, 20:11  [ТС]     Наследование. Виртуальные методы/деструкторы. #5
Спасибо
теперь всё понятно...
zzz_
5 / 5 / 0
Регистрация: 08.05.2011
Сообщений: 215
01.05.2012, 17:18     Наследование. Виртуальные методы/деструкторы. #6
Цитата Сообщение от Nick Alte Посмотреть сообщение
Cell *ptr = new Prey();
Что это вообще означает? Почему бы не сделать так
C++
1
Prey *ptr = new Prey()
Зачем вообще он нужен этот деструктор?
Если мы статически создаем Prey p, то при завершении удалится и cell, верно?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.05.2012, 22:25     Наследование. Виртуальные методы/деструкторы.
Еще ссылки по теме:

C++ Виртуальные деструкторы
Наследование и виртуальные методы C++
Наследование и виртуальные функции C++

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

Или воспользуйтесь поиском по форуму:
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
01.05.2012, 22:25  [ТС]     Наследование. Виртуальные методы/деструкторы. #7
Статически - да.
но представь - есть массив, где в перемешку Cell, Prey, Predator - всё сразу. Как его описать? только каак массив из "предков", то есть из "Cell".
PureBasic
1
vector<Cell*> vec;
вот и возникает ситуация, когда указатель типа Cell указывает на "данные", типа Prey
Yandex
Объявления
01.05.2012, 22:25     Наследование. Виртуальные методы/деструкторы.
Ответ Создать тему
Опции темы

Текущее время: 20:55. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru