2月
26
C++11 には仮想関数をそれ以上オーバーライドできないようにする final という指定が書けますが、final が付いていると呼ぶときに vtable を参照して間接callするのではなく直接呼ぶようになります。(とりあえず GCC の場合)
[umezawa@umezawa-cent7:pts/0 ~]$ cat a.cc
struct A {
virtual void foo();
};
struct B : public A {
virtual void foo() final;
};
struct C : public A {
virtual void foo();
};
void bar(B* b)
{
b->foo();
}
void baz(C* c)
{
c->foo();
}
[umezawa@umezawa-cent7:pts/0 ~]$ g++ -std=c++11 -S -o- -O0 a.cc
.file "a.cc"
.text
.globl _Z3barP1B
.type _Z3barP1B, @function
_Z3barP1B:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movq %rax, %rdi
call _ZN1B3fooEv
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size _Z3barP1B, .-_Z3barP1B
.globl _Z3bazP1C
.type _Z3bazP1C, @function
_Z3bazP1C:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq -8(%rbp), %rdx
movq %rdx, %rdi
call *%rax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size _Z3bazP1C, .-_Z3bazP1C
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-16)"
.section .note.GNU-stack,"",@progbits
興味深いのは最適化なしでもそうなるという点でしょうか。
直接呼ばれるとシンボルを参照するようになるため、リンク順でハマるケースがあるかもしれません。
no comment untill now