C++虚函数调用规则

C++虚函数调用规则

基类、派生类结构:

class Foo {
public:
    virtual void print() {
        cout << "Foo" << endl;
    }
};
class Bar : public Foo {
public:
    virtual void print() {
        cout << "Bar" << endl;
    }
};

1.通过对象直接调用虚函数

通过对象直接调用虚函数,不涉及到虚函数表指针的访问(g++,MSVC,clang++测试结果一致)

Foo foo;
foo.print();
Bar bar;
bar.print();

foo.print()与bar.print()对应的汇编:

# foo.print
lea     rdi, [rbp - 16]
call    Foo::print()
# bar.print
lea     rdi, [rbp - 24]
call    Bar::print()

2.通过基类的引用调用虚函数

通过基类的引用调用虚函数,不同编译器的表现不同

Foo foo;
Bar bar;
Foo& r1=foo;
r1.print();
Foo& r2=bar;
r2.print();
  • clang编译器,不管引用的是基类对象还是派生类对象,调用虚函数都要访问虚函数表指针

    #r1.print:
    mov     rax, qword ptr [rdi]
    call    qword ptr [rax]
    #r2.print:
    mov     rax, qword ptr [rdi]
    call    qword ptr [rax]
    
  • g++编译器,当引用基类对象时,调用虚函数不涉及到虚函数表指针的访问,引用派生类对象时,调用虚函数涉及到虚函数表指针的访问

    #r1.print:
    ldr     r0, [r7, #12]
    bl      Foo::print()
    #r2.print:
    ldr     r3, [r7, #8]
    ldr     r3, [r3]
    ldr     r3, [r3]
    ldr     r0, [r7, #8]
    blx     r3
    

补充:使用派生类的引用调用虚函数

Bar bar;
Bar& r=bar;
r.print();

g++编译器:不涉及虚函数表指针的访问

ldr     r0, [r7, #4]
bl      Bar::print()

clang编译器:涉及到虚函数表指针的访问

 mov     rax, qword ptr [rdi]
 call    qword ptr [rax]

3.使用指针调用虚函数

使用指针调用虚函数时,均涉及到虚函数表指针的访问(在g++和clang编译器下表现相同)

Foo foo;
Bar bar;
Foo* p1=&foo;
Foo* p2=&bar;
Bar* p3=&bar;
p1->print();
p2->print();
p3->print();

p1、p2、p3调用print函数的汇编:

mov     rax, qword ptr [rdi]
call    qword ptr [rax]
mov     rdi, qword ptr [rbp - 40]
mov     rax, qword ptr [rdi]
call    qword ptr [rax]
mov     rdi, qword ptr [rbp - 48]
mov     rax, qword ptr [rdi]
call    qword ptr [rax]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值