Eri*_*ois 5 c++ optimization virtual inheritance inline
在派生类中调用虚函数的最佳方法是什么,以便编译器可以内联或以其他方式优化调用?
例:
class Base {
virtual void foo() = 0;
};
class Derived: public Base {
virtual void foo() {...}
void bar() {
foo();
}
};
Run Code Online (Sandbox Code Playgroud)
我希望打电话foo()进来bar()随时打电话Derived::foo().我的理解是,调用将导致vtable查找,并且编译器无法优化它,因为可能有另一个继承自Derived的类.
我可以显式调用Derived::foo()但是如果Derived中有许多虚函数调用则会变得冗长.我也发现令人惊讶的是我找不到很多在线资料来解决我认为是常见的情况(一个'最终'派生类调用虚拟方法)所以我想知道我是在滥用虚函数还是过度优化.
该怎么做?停止过早优化和坚持foo(),吸收和使用Derived::foo(),还是有更好的方法?
C++ 11包含final关键字,"指定不能在派生类中重写虚函数或者不能继承类." 1.
似乎g ++能够优化派生类中的虚函数调用(如果已声明)final.
我创建了以下测试:
virtualFunctions.h
#pragma once
class Base {
public:
virtual void foo();
virtual void bar();
virtual void baz();
int fooVar, barVar, bazVar;
};
class Derived: public Base {
public:
void test();
virtual void foo();
virtual void bar();
virtual void baz() final;
};
Run Code Online (Sandbox Code Playgroud)
virtualFunctions.cpp:
#include "virtualFunctions.h"
void Derived::test() {
foo();
Derived::bar();
baz();
}
void Derived::foo() {
fooVar = 101;
}
void Derived::bar() {
barVar = 202;
}
void Derived::baz() {
bazVar = 303;
}
Run Code Online (Sandbox Code Playgroud)
我使用g ++ 4.7.2和-O1生成的程序集包含:
_ZN7Derived4testEv:
.LFB0:
.loc 1 3 0
.cfi_startproc
.LVL3:
pushl %ebx
.LCFI0:
.cfi_def_cfa_offset 8
.cfi_offset 3, -8
subl $24, %esp
.LCFI1:
.cfi_def_cfa_offset 32
movl 32(%esp), %ebx ; Load vtable from the stack
.loc 1 4 0
movl (%ebx), %eax ; Load function pointer from vtable
movl %ebx, (%esp)
call *(%eax) ; Call the function pointer
.LVL4:
.loc 1 5 0
movl %ebx, (%esp)
call _ZN7Derived3barEv ; Direct call to Derived::bar()
.LVL5:
.loc 1 6 0
movl %ebx, (%esp)
call _ZN7Derived3bazEv ; Devirtualized call to Derived::baz()
Run Code Online (Sandbox Code Playgroud)
Derived::bar()并且Derived::baz()都被直接调用,而vtable则用于foo().