Виртуальные вызовы с помощью адреса чистого виртуального участника. Действительно ли это законно?

Рассматривали ли вы упаковку ExecutorService? Создайте

CleanShutdownExecutorService implements Executor 

, который делегирует все вызовы другому исполнителю, но сохраняет фьючерсы в своем собственном списке. CleanShutdownExecutorService может затем иметь метод cancelRemainingTasks (), который вызывает shutdown (), а затем вызывает cancel (false) для всех фьючерсов в своем списке.

5
задан Abhay 12 June 2009 в 08:48
поделиться

4 ответа

This following article extensively discusses member function pointers in C++, how they are implemented and where are the flaws. It also handles virtual member function pointers and much more. I think it will answer all your questions.

http://www.codeproject.com/KB/cpp/FastDelegate.aspx

It also shows how to implement delegates in C++ and what pitfalls you might trap in.

With Kind Regards,

Ovanes

1
ответ дан 15 December 2019 в 06:33
поделиться

Конечно, это так. Ваш код ничем не отличается от простого вызова чистого виртуального метода следующим образом:

void Test()
{ 
   Base* ptr = new Derived; 
   ptr->sayHi();
   delete ptr;
} 

Единственное отличие состоит в том, что у вас есть другой механизм для выполнения вызова, и в данном случае через callVirtual ().

1
ответ дан 15 December 2019 в 06:33
поделиться

Как сказал Магнус Ског, часть шаблона на самом деле не актуальна. Все сводится к следующему:

(ptr->* &Base::sayHi)()

похоже работает, но

ptr->Base::sayHi()

явно не работает, потому что sayHi является чисто виртуальным.

Мне не удалось найти ничего в стандарте о том, что происходит, когда вы берете адрес виртуальной или чистой виртуальной функции. Я не уверен, что это законно. Тем не менее, он работает в GCC и MSVC, и онлайн-компилятор Comeau тоже не жалуется.

Править

Даже если он действителен, как говорят ваши правки, мне все еще интересно, что это значит.

Если мы для простоты предположим, что sayHi не является чистым (поэтому существует определение Base :: sayHi ), тогда что произойдет, если я возьму его адрес? Получу ли я адрес Base :: sayHi, Вызов ptr-> Base :: sayHi () вызывает sayHi в базовом классе, но взяв адрес Base :: sayHi , я получаю адрес Получено :: sayHi

Мне это кажется непоследовательным. Есть ли какое-то объяснение того, что мне не хватает?

1
ответ дан 15 December 2019 в 06:33
поделиться

Я предполагаю, что это неопределенный. Я ничего не нашел в спецификации.

виртуальные методы реализованы с использованием концепции, называемой vtable .

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

Я только что скомпилировал ваш код с помощью Visual Studio 2008 и скомпилировал exe.j _ ?? _ 9Base @ @ $ B3AE

; void __thiscall Base___vcall_(Base *)
j_??_9Base@@$B3AE proc near
jmp     ??_9Base@@$B3AE ; [thunk]: Base::`vcall'{4,{flat}}
j_??_9Base@@$B3AE endp

Все, что делает thunk-функция, это использует vtable для перехода к методу реального класса.

0
ответ дан 15 December 2019 в 06:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: