quote:Original post by Arild Fines
If you call a virtual method from a derived class pointer in C++, there will be a virtual lookup. If the compiler had been able to recognize the derived as a final class(or that this particular method was declared final)
If you add inline to the method declaration, and make the call using an explicit class declaration, the virtual call can be removed as follows:
ex.
struct Base#include <iostream>using namespace std;struct Base { inline virtual Test()=0 { cout<<"Base"<<endl; } };struct Sub : Base { Sub() { //Always call Base::Test, never anything else. //Similar effect to final, except you decide // at the invocation point, not at the class declaration //More flexibility, but more work too this->Base::Test(); } inline virtual Test() { cout<<"Sub"<<endl; } };int main(){ Sub sub; return 0;}
Assembly output showing optimization, which has completely removed all method calls (virtual or otherwise), the cout is invoked directly inside of main.
; Listing generated by Microsoft (R) Optimizing Compiler Version 13.00.9466 TITLE Crap4.cpp .386Pinclude listing.incif @Version gt 510.model FLAT;***SNIP***PUBLIC _main; Function compile flags: /Ogty; COMDAT _main_TEXT SEGMENT_main PROC NEAR ; COMDAT; 33 : { push esi; 34 : Sub sub; push OFFSET FLAT:??_C@_04NGEJNKEG@Base?$AA@ push OFFSET FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::cout call ??6std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<< add esp, 8 mov esi, eax push 10 ; 0000000aH mov ecx, esi call ?put@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV12@D@Z ; std::basic_ostream<char,std::char_traits<char> >::put mov ecx, esi call ?flush@?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV12@XZ ; std::basic_ostream<char,std::char_traits<char> >::flush; 35 : return 0; xor eax, eax pop esi; 36 : } ret 0_main ENDP
I reassert that final does not enable any optimizations, it merely removes bloat.