Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / pure virtual function call или как-то так... / 20 сообщений из 20, страница 1 из 1
25.11.2010, 22:42
    #36977985
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Недавно наткнулся на такое сообщение в студии. А у меня однажды аська упала с таким же сообщением. И я все думал: как такое может быть. И тут понял.

Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен.

Это же, наверное, странно что виртуальные функции не работают в конструкторах, но работают в деструкторах (приводят к падению). В чем причина ?
...
Рейтинг: 0 / 0
26.11.2010, 00:13
    #36978042
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
petravНедавно наткнулся на такое сообщение в студии. А у меня однажды аська упала с таким же сообщением. И я все думал: как такое может быть. И тут понял.

Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен.

Это же, наверное, странно что виртуальные функции не работают в конструкторах, но работают в деструкторах (приводят к падению). В чем причина ?
Во-первых вызов неабстрактных виртуальных функций работает и в конструкторе и деструкторе (просто работает не так как ожидается интуитивно)
Во-вторых, вызов абстрактного метода приводит к падению и в деструкторе и в конструкторе абстрактного класса.
Явно вызвать абстрактный метод конечно нормальный компилятор не даст, как минимум такая программа не должна слинковаться.
Поэтому если возникает указанная ошибка то значит применили какойто хак типа этого:
Код: plaintext
1.
2.
3.
4.
5.
 
A() {
    A* a = this;
    a->f();
}
Тут не важно в конструкторе это или деструкторе.
...
Рейтинг: 0 / 0
26.11.2010, 17:20
    #36979858
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
On 26.11.2010 0:13, Anatoly Moskovsky wrote:

> Во-первых вызов неабстрактных виртуальных функций *работает *и в конструкторе и
> деструкторе (просто работает не так как ожидается интуитивно)

Я бы сказал обратное.


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

Это неверно. Он не даст инстанциировать наследника без переопределения
этого метода.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
26.11.2010, 18:10
    #36980015
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
У меня в результате тривиальной ошибки получался такой фокус. Не воспроизведу - не помню.
...
Рейтинг: 0 / 0
26.11.2010, 18:23
    #36980059
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Кажется вспомнил. Из конструктора и компилятор пропустил )

Если не вру - в конструкторе вызов любой функции невиртуальный, а вот в деструкторе все вызывается правильно (наследника).

Тогда petrav ошибается во фразе - "Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен."
...
Рейтинг: 0 / 0
26.11.2010, 18:38
    #36980093
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Siemargl, это делается так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
#include <iostream>

using namespace std;
struct base
{
	base() { foo(); }

	void foo() { init(); }
	virtual void init() =  0 ;
};

struct child : public base
{
	virtual void init() { cout << "oops!" << endl; }
};


int main( int argc, char *argv[] )
{
	child pure;

	return  0 ;
}
;-))
...
Рейтинг: 0 / 0
26.11.2010, 19:11
    #36980155
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
SiemarglТогда petrav ошибается во фразе - "Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен."
Нет, у меня вызывалась читая виртуальная функция именно в деструкторе базового объекта - базовый класс занимался разрегистрацией в некотором менеджере и ему нужен был Reference Name (строка) объекта. И функция именно эту строку и возвращала.

Пришлось перенести значение RefName в базовый класс.

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

Вот интересно что бы было если бы у чистой виртуальной функции в базовом классе было бы тело... =)
...
Рейтинг: 0 / 0
26.11.2010, 19:20
    #36980164
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Anatoly MoskovskyВо-вторых, вызов абстрактного метода приводит к падению и в деструкторе и в конструкторе абстрактного класса.
Явно вызвать абстрактный метод конечно нормальный компилятор не даст, как минимум такая программа не должна слинковаться.
Поэтому если возникает указанная ошибка то значит применили какойто хак типа этого:
Код: plaintext
1.
2.
3.
4.
5.
 
A() {
    A* a = this;
    a->f();
}
Тут не важно в конструкторе это или деструкторе.
Но ведь, дал вызвать и без хаков, натюрлих. VS 2010.

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

Вот уж не знал.
...
Рейтинг: 0 / 0
26.11.2010, 21:34
    #36980309
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
MasterZiv> Явно вызвать абстрактный метод конечно нормальный компилятор не даст, как
> минимум такая программа не должна слинковаться.

Это неверно. Он не даст инстанциировать наследника без переопределения
этого метода.

Тут рассматривается другая ситуация - когда в наследнике все правильно переопределено, а вызов происходит в конструкторе/деструкторе предка.
...
Рейтинг: 0 / 0
26.11.2010, 22:08
    #36980357
petrav
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Anatoly MoskovskyПоэтому если возникает указанная ошибка то значит применили какойто хак типа этого:
Код: plaintext
1.
2.
3.
4.
5.
 
A() {
    A* a = this;
    a->f();
}
Тут не важно в конструкторе это или деструкторе.
Мда... Anatoly Moskovsky ... вы как всегда. Слов нет.

Так и было.

Я тут задумался над своим описанием своей же ситуации.

Подумал что менеджеру то RefName нафиг не нужен. Посмотрел свой же код - базовый класс в деструкторе передает менеджеру свой указатель на разрегистрацию. А уже менеджер зовет чистую виртуальную функцию объекта, возвращающую не RefName, а другую характеристику объекта (числовую). Он по ней разбрасывает объекты по массивам.

Вы правы, как всегда. Ну или почти всегда. =)
...
Рейтинг: 0 / 0
26.11.2010, 22:46
    #36980395
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
SiemarglЕсли не вру - в конструкторе вызов любой функции невиртуальный, а вот в деструкторе все вызывается правильно (наследника).
Согласно стандарту 2003:
10.4.6. Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or
destroyed) from such a constructor (or destructor) is undefined .
...
Рейтинг: 0 / 0
27.11.2010, 00:11
    #36980476
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
SiemarglУ меня в результате тривиальной ошибки получался такой фокус. Не воспроизведу - не помню.

Это либо в конструкторе / деструкторе, либо после срезки объекта до абстрактной базы.
...
Рейтинг: 0 / 0
27.11.2010, 00:17
    #36980479
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Siemargl
Если не вру - в конструкторе вызов любой функции невиртуальный, а вот в деструкторе все вызывается правильно (наследника).


Все вызовы виртуальных методов без явной квалификации класса делаются виртуально.
(может ещё какие-то есть случаи, но в основном это так).

В конструкторе и деструкторе наследника при вызове виртуального метода вызовится реализация
из этого наследника. В конструкторе и деструкторе предка (абстрактного или нет)
вызовится реализация из этого предка, но не потому, что виртуальная функция перестаёт
быть виртуальной или "не работает", а потому, что в этот момент объект ещё (в случае констуктора) или уже
(в случае деструктора) НЕ ЯВЛЯЕТСЯ объектом класса-наследника, а является объектом класса-предка.
...
Рейтинг: 0 / 0
27.11.2010, 00:36
    #36980489
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
MasterZiv,

Согласен, соврал

проверка
Код: plaintext
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.
35.
#include <iostream>

using namespace std;
struct base
{
	base() {  virt_a(); }
	virtual ~base() {  virt_b(); }

	virtual void virt_a() { cout << "base _a()" << endl; };
	virtual void virt_b() { cout << "base _b()" << endl; };
};

struct child : public base
{
	child() { cout << "child create()" << endl;  }
	virtual ~child() {  cout << "~child" << endl; }
	
	virtual void virt_a() { cout << "child _a()" << endl; };
	virtual void virt_b() { cout << "child _b()" << endl; };
};


int main()
{
	base *p = new child;
	delete p;	

	return  0 ;
}

D:\_workplace\virtual_destr>a.exe
base _a()
child create()
~child
base _b()
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
03.06.2013, 18:09
    #38284161
Николаев А. Н. Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
MasterZivSiemarglЕсли не вру - в конструкторе вызов любой функции невиртуальный, а вот в деструкторе все вызывается правильно (наследника).


Все вызовы виртуальных методов без явной квалификации класса делаются виртуально.
(может ещё какие-то есть случаи, но в основном это так).

В конструкторе и деструкторе наследника при вызове виртуального метода вызовится реализация
из этого наследника. В конструкторе и деструкторе предка (абстрактного или нет)
вызовится реализация из этого предка, но не потому, что виртуальная функция перестаёт
быть виртуальной или "не работает", а потому, что в этот момент объект ещё (в случае констуктора) или уже
(в случае деструктора) НЕ ЯВЛЯЕТСЯ объектом класса-наследника, а является объектом класса-предка.
Логичное объяснение!
...
Рейтинг: 0 / 0
04.06.2013, 11:51
    #38284923
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
petravНедавно наткнулся на такое сообщение в студии. А у меня однажды аська упала с таким же сообщением. И я все думал: как такое может быть. И тут понял.

Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен.

Это же, наверное, странно что виртуальные функции не работают в конструкторах, но работают в деструкторах (приводят к падению). В чем причина ?

Причину ты уже сам написал, все правильно, кроме одного момента — виртуальные методов одинаково работают и в конструкторах, и в деструкторах.

А именно — вызывается реализация из того класса, экземпляром которого в данный момент является объект.

"проблема" заключается в том, что при конструировании и деструировании класс объекта меняется, сначала соответственно сверху иерархии вниз (от предка к конечному наследнику), а потом наоборот вверх, от наследника к предку.


Если тебе это мешает , ты можешь реализовать в базовом классе этот метод, даже если он абстрактный, и падения программы в этом случае нее будет.
...
Рейтинг: 0 / 0
04.06.2013, 11:53
    #38284927
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Блин, какой редиск пнул тему?
...
Рейтинг: 0 / 0
04.06.2013, 12:43
    #38285002
Николаев А. Н. Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
MasterZivБлин, какой редиск пнул тему?
Ахаха.
...
Рейтинг: 0 / 0
04.06.2013, 12:54
    #38285034
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
Николаев А. Н. Н., хохотун ты когда нагуглил тему, то хоть даты смотри. А то вступишь в переписку
с Эйнштейном и Бором, некромант ты наш ненаглядный
...
Рейтинг: 0 / 0
04.06.2013, 13:41
    #38285143
Николаев А. Н. Н.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
pure virtual function call или как-то так...
maytonНиколаев А. Н. Н., хохотун ты когда нагуглил тему, то хоть даты смотри. А то вступишь в переписку
с Эйнштейном и Бором, некромант ты наш ненаглядный
Я считаю, истина бессмертна.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / pure virtual function call или как-то так... / 20 сообщений из 20, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]