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

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

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

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

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

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

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


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

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

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

Тогда petrav ошибается во фразе - "Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен."
...
Рейтинг: 0 / 0
pure virtual function call или как-то так...
    #36980093
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
pure virtual function call или как-то так...
    #36980155
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglТогда petrav ошибается во фразе - "Виртуальная функция переопределенная в наследнике вызвана в деструкторе базового класса. Т.е. когда объект наследник уже уничтожен."
Нет, у меня вызывалась читая виртуальная функция именно в деструкторе базового объекта - базовый класс занимался разрегистрацией в некотором менеджере и ему нужен был Reference Name (строка) объекта. И функция именно эту строку и возвращала.

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

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

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

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

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

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

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

Так и было.

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

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

Вы правы, как всегда. Ну или почти всегда. =)
...
Рейтинг: 0 / 0
pure virtual function call или как-то так...
    #36980395
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
pure virtual function call или как-то так...
    #36980476
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglУ меня в результате тривиальной ошибки получался такой фокус. Не воспроизведу - не помню.

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


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

В конструкторе и деструкторе наследника при вызове виртуального метода вызовится реализация
из этого наследника. В конструкторе и деструкторе предка (абстрактного или нет)
вызовится реализация из этого предка, но не потому, что виртуальная функция перестаёт
быть виртуальной или "не работает", а потому, что в этот момент объект ещё (в случае констуктора) или уже
(в случае деструктора) НЕ ЯВЛЯЕТСЯ объектом класса-наследника, а является объектом класса-предка.
...
Рейтинг: 0 / 0
pure virtual function call или как-то так...
    #36980489
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Период между сообщениями больше года.
pure virtual function call или как-то так...
    #38284161
Николаев А. Н. Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivSiemarglЕсли не вру - в конструкторе вызов любой функции невиртуальный, а вот в деструкторе все вызывается правильно (наследника).


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

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

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

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

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

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

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


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


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