Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: [c++] abstract virtual destructor  (Прочитано 6345 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Mayor
Специалист

ru
Offline Offline

« : 19-08-2009 14:58 » 

[c++] abstract virtual destructor

Код:
#ifndef window_cairo__HH
#define window_cairo__HH
struct point {
int x;
int y;
point(int a,int b) : x(a),y(b) { } ;
};
#include <iostream>
using std::cout;
using std::endl;
class window {
public:
virtual point current() =0 ;
virtual void current(const point& p) = 0;
virtual void line(const point& p) =0;
virtual void paint()=0;
virtual ~window() {
cout<<"destroing abstract window"<<endl;
};
};
#endif

#ifndef xlib_window__HH
#define xlib_window__HH
#include "window.h"
#include<cairo-xlib.h>
class xlib_window : public window {
Display *dpy;
Window rootwin;
Window win;
int scr;
cairo_t *cr;
cairo_surface_t *surface;
point p;
public:
xlib_window(int x=500,int y=300,const char* pc="hello");
virtual point current();
virtual void current(const point& cp);
virtual void line(const point& p) ;
virtual void paint();
virtual ~xlib_window();
};
#endif

#include "xlib_cairo_window.h"

window* window_factory(string class_name,
int x,int y ,const char* pc) {
if (class_name=="1") x++;
window *p=new xlib_window(x,y,pc);
return p;
}


#include "factory.h"
#include <iostream>
int main() {
window* p=window_factory("asdf",400,500,"alpha");
p->paint();
delete p;
        return 0;
}
// не скомпилится тк не выложил реализацию xlib cairo window

как отключить предупреждение компилятора, о невиртуальном деструкторе только в абстрактном классе window?

после определения виртуального деструктора в абстрактном классе window, он стал зачем-то вызываться в delete p - это я неправильно определил деструктор в наследуемом классе или недопонял стандарт с++ ?



Записан

1n c0de we trust
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 19-08-2009 16:40 » 

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

window *p=new xlib_window(x,y,pc);
delete p;//вызовется ~xlib_window(), ~window()
p=0;


window *p=new window(x,y,pc);
delete p;//вызовется ~window()
p=0;

-------------------------
А если сделать деструктор не виртуальным, то будет такой результат

window *p=new xlib_window(x,y,pc);
delete p;//вызовется  ~window()
p=0;


window *p=new window(x,y,pc);
delete p;//вызовется ~window()
p=0;

Записан

Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 19-08-2009 17:37 » 

В чём, собственно, проблема? Виртуальный деструктор нужен для того, чтобы корректно освобождать память под потомками по указателю на предка. Если ты этого не сделешь, произойдёт некорректное (неполное) уничтожение объекта. Так что не надо у абстрактного класса убирать виртуальный деструктор, и компилятор всё правильно предупреждает.
Записан
Mayor
Специалист

ru
Offline Offline

« Ответ #3 : 20-08-2009 13:58 » 

В чём, собственно, проблема? ...
... Так что не надо у абстрактного класса убирать виртуальный деструктор, и компилятор всё правильно предупреждает.

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

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

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

да кстати относительно понимания: в xlib_window слова virtual уже лишние?

а может нужно было сделать в абстрактном классе деструктор тоже абстрактным?
« Последнее редактирование: 20-08-2009 14:01 от Mayor » Записан

1n c0de we trust
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 20-08-2009 16:06 » 

Деструкторы предков вызываются потому, что только они заботятся об освобождении данных, хранимых этими предками. Поэтому любой деструктор потомка содержит неявный вызов деструктора предка (точнее, деструкторов всех прямых предков - может иметь место множественное наследование).

Виртуальный же деструктор отличается от обычного только тем, что в виртуальную таблицу заносится адрес деструктора потомка, чтобы при вызове delete для указателя на предок можно было корректно освободить объект, на самом деле являющийся потомком, вызвав его деструктор. Дальше цепочка вызовов деструкторов ничем не отличается от цепочки при вызове delete для потомка.

Вторично virtual для метода потомка можно уже не указывать. Если совпадает имя и сигнатура, он в любом случае будет виртуальным, если метод предка виртуальный.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines