当前位置: 首页 > article >正文

类实例化和构造函数

类实例化和构造函数

  • 类如何创立,如何调用构造函数
    • 源码
    • rv汇编
    • 行为分析
  • 一般成员函数
  • 虚函数
    • 源码
    • 汇编
    • 行为分析
  • 纯虚函数
    • 汇编
    • 行为分析
  • 多态
    • 源码
    • 汇编
    • 行为分析
  • 为什么构造函数不能是虚函数

类如何创立,如何调用构造函数

源码

#include <iostream>
using namespace std;

// 抽象父类
class Base {
    int a,b;
public:
    Base(){
        a=1;
        b=2;
    }

};

// 子类
class Derived : public Base {
public:
    int c;
    Derived(){
        c=3;
    }
};

int main() {
    Derived b ; 
    return 0;
}

rv汇编

__cxx_global_var_init:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        lui     a0, %hi(std::__ioinit)
        addi    a0, a0, %lo(std::__ioinit)
        sw      a0, -12(s0)
        call    std::ios_base::Init::Init() [complete object constructor]
        lw      a1, -12(s0)
        lui     a0, %hi(_ZNSt8ios_base4InitD1Ev)
        addi    a0, a0, %lo(_ZNSt8ios_base4InitD1Ev)
        lui     a2, %hi(__dso_handle)
        addi    a2, a2, %lo(__dso_handle)
        call    __cxa_atexit
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

main:
        addi    sp, sp, -32
        sw      ra, 28(sp)
        sw      s0, 24(sp)
        addi    s0, sp, 32
        mv      a0, zero
        sw      a0, -28(s0)
        sw      a0, -12(s0)
        addi    a0, s0, -24
        call    Derived::Derived() [base object constructor]
        lw      a0, -28(s0)
        lw      s0, 24(sp)
        lw      ra, 28(sp)
        addi    sp, sp, 32
        ret

Derived::Derived() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        sw      a0, -16(s0)
        call    Base::Base() [base object constructor]
        lw      a1, -16(s0)
        addi    a0, zero, 3
        sw      a0, 8(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::Base() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a1, -12(s0)
        addi    a0, zero, 1
        sw      a0, 0(a1)
        addi    a0, zero, 2
        sw      a0, 4(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

_GLOBAL__sub_I_example.cpp:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        call    __cxx_global_var_init
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

std::__ioinit:
        .zero   1

行为分析

  • 在main会去调用Derived的构造函数,并且在调用之前,会给a0寄存器一个地址,这个地址其实是this指针,也就是Derived实例化对象b的地址,main在传入之前已经为b实例开辟了栈空间
  • Derived的构造函数的也会传入b的地址给Base的构造函数
  • 进入Base构造就不难看出,这里拿着最开始b的地址在做实际的输出化了
        lw      a1, -12(s0)
        addi    a0, zero, 1
        sw      a0, 0(a1)
        addi    a0, zero, 2
        sw      a0, 4(a1)
        lw      s0, 8(sp)

这里是先把地址放在栈上,然后a1拿着地址,之后就往偏移位置放值,这里对应的就是初始化父类的成员变量

  • 调用完回到Derived的构造函数,再初始化子类成员变量
        lw      a1, -16(s0)
        addi    a0, zero, 3
        sw      a0, 8(a1)

一般成员函数

#include <iostream>
using namespace std;

// 抽象父类
class Base {
    int a,b;
public:
    Base(){
        a=1;
        b=2;
    }

};

// 子类
class Derived : public Base {
public:
    int c;
    Derived(){
        c=3;
    }
    void show(){
        cout<<c<<endl;
    }
};

int main() {
    Derived b ; 
    b.show();
    return 0;
}

这里其实和构造函数一样,调用之气会传入变量的地址,也就是this指针,以便函数使用成员变量

虚函数

源码

#include <iostream>
using namespace std;


class Base {
public:
    int a,b;
    Base(){
        a=1;
        b=2;
    }
    virtual void show1(){
        cout<<a<<endl;
    }
    virtual void show2(){
        cout<<a<<endl;
    }

};

// 子类
class Derived : public Base {
public:
    int c;
    Derived(){
        c=3;
    }

    virtual void show2(){
        cout<<a<<endl;
    }
};

int main() {
    Derived b ; 
    b.show1();
    return 0;
}

汇编

__cxx_global_var_init:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        lui     a0, %hi(std::__ioinit)
        addi    a0, a0, %lo(std::__ioinit)
        sw      a0, -12(s0)
        call    std::ios_base::Init::Init() [complete object constructor]
        lw      a1, -12(s0)
        lui     a0, %hi(_ZNSt8ios_base4InitD1Ev)
        addi    a0, a0, %lo(_ZNSt8ios_base4InitD1Ev)
        lui     a2, %hi(__dso_handle)
        addi    a2, a2, %lo(__dso_handle)
        call    __cxa_atexit
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

main:
        addi    sp, sp, -48
        sw      ra, 44(sp)
        sw      s0, 40(sp)
        addi    s0, sp, 48
        mv      a0, zero
        sw      a0, -36(s0)
        sw      a0, -12(s0)
        addi    a0, s0, -32
        sw      a0, -40(s0)
        call    Derived::Derived() [base object constructor]
        lw      a0, -40(s0)
        call    Base::show1()
        lw      a0, -36(s0)
        lw      s0, 40(sp)
        lw      ra, 44(sp)
        addi    sp, sp, 48
        ret

Derived::Derived() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        sw      a0, -16(s0)
        call    Base::Base() [base object constructor]
        lw      a1, -16(s0)
        lui     a0, %hi(vtable for Derived)
        addi    a0, a0, %lo(vtable for Derived)
        addi    a0, a0, 8
        sw      a0, 0(a1)
        addi    a0, zero, 3
        sw      a0, 12(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::show1():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::Base() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a1, -12(s0)
        lui     a0, %hi(vtable for Base)
        addi    a0, a0, %lo(vtable for Base)
        addi    a0, a0, 8
        sw      a0, 0(a1)
        addi    a0, zero, 1
        sw      a0, 4(a1)
        addi    a0, zero, 2
        sw      a0, 8(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Derived::show2():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::show2():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

_GLOBAL__sub_I_example.cpp:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        call    __cxx_global_var_init
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

std::__ioinit:
        .zero   1

vtable for Derived:
        .word   0
        .word   typeinfo for Derived
        .word   Base::show1()
        .word   Derived::show2()

typeinfo name for Derived:
        .asciz  "7Derived"

typeinfo name for Base:
        .asciz  "4Base"

typeinfo for Base:
        .word   _ZTVN10__cxxabiv117__class_type_infoE+8
        .word   typeinfo name for Base

typeinfo for Derived:
        .word   _ZTVN10__cxxabiv120__si_class_type_infoE+8
        .word   typeinfo name for Derived
        .word   typeinfo for Base

vtable for Base:
        .word   0
        .word   typeinfo for Base
        .word   Base::show1()
        .word   Base::show2()

行为分析

有虚函数的话,对象的首地址就会设置为虚函数表的位置,然后父类设置之后子类再设置覆盖掉。

纯虚函数

源码

#include <iostream>
using namespace std;


class Base {
public:
    int a,b;
    Base(){
        a=1;
        b=2;
    }
    virtual void show1(){
        cout<<a<<endl;
    }
    virtual void show2()=0;

};

// 子类
class Derived : public Base {
public:
    int c;
    Derived(){
        c=3;
    }

    virtual void show2(){
        cout<<a<<endl;
    }
};

int main() {
    Derived b ; 
    b.show1();
    return 0;
}

汇编

__cxx_global_var_init:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        lui     a0, %hi(std::__ioinit)
        addi    a0, a0, %lo(std::__ioinit)
        sw      a0, -12(s0)
        call    std::ios_base::Init::Init() [complete object constructor]
        lw      a1, -12(s0)
        lui     a0, %hi(_ZNSt8ios_base4InitD1Ev)
        addi    a0, a0, %lo(_ZNSt8ios_base4InitD1Ev)
        lui     a2, %hi(__dso_handle)
        addi    a2, a2, %lo(__dso_handle)
        call    __cxa_atexit
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

main:
        addi    sp, sp, -48
        sw      ra, 44(sp)
        sw      s0, 40(sp)
        addi    s0, sp, 48
        mv      a0, zero
        sw      a0, -36(s0)
        sw      a0, -12(s0)
        addi    a0, s0, -32
        sw      a0, -40(s0)
        call    Derived::Derived() [base object constructor]
        lw      a0, -40(s0)
        call    Base::show1()
        lw      a0, -36(s0)
        lw      s0, 40(sp)
        lw      ra, 44(sp)
        addi    sp, sp, 48
        ret

Derived::Derived() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        sw      a0, -16(s0)
        call    Base::Base() [base object constructor]
        lw      a1, -16(s0)
        lui     a0, %hi(vtable for Derived)
        addi    a0, a0, %lo(vtable for Derived)
        addi    a0, a0, 8
        sw      a0, 0(a1)
        addi    a0, zero, 3
        sw      a0, 12(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::show1():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::Base() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a1, -12(s0)
        lui     a0, %hi(vtable for Base)
        addi    a0, a0, %lo(vtable for Base)
        addi    a0, a0, 8
        sw      a0, 0(a1)
        addi    a0, zero, 1
        sw      a0, 4(a1)
        addi    a0, zero, 2
        sw      a0, 8(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Derived::show2():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

_GLOBAL__sub_I_example.cpp:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        call    __cxx_global_var_init
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

std::__ioinit:
        .zero   1

vtable for Derived:
        .word   0
        .word   typeinfo for Derived
        .word   Base::show1()
        .word   Derived::show2()

typeinfo name for Derived:
        .asciz  "7Derived"

typeinfo name for Base:
        .asciz  "4Base"

typeinfo for Base:
        .word   _ZTVN10__cxxabiv117__class_type_infoE+8
        .word   typeinfo name for Base

typeinfo for Derived:
        .word   _ZTVN10__cxxabiv120__si_class_type_infoE+8
        .word   typeinfo name for Derived
        .word   typeinfo for Base

vtable for Base:
        .word   0
        .word   typeinfo for Base
        .word   Base::show1()
        .word   __cxa_pure_virtual

行为分析

抽象类的虚函数表里标注了纯虚函数,这里是找不到base的show2实现的

vtable for Base:
        .word   0
        .word   typeinfo for Base
        .word   Base::show1()
        .word   __cxa_pure_virtual

行为和没有纯虚函数一样,也是替换表

多态

源码

#include <iostream>
using namespace std;

class Base {
public:
    int a,b;
    Base(){
        a=1;
        b=2;
    }
    virtual void show2(){
        cout<<a<<endl;
    }
    virtual void show1(){
        cout<<a<<endl;
    }


};

// 子类
class Derived : public Base {
public:
    int c;
    Derived(){
        c=3;
    }

    virtual void show2(){
        cout<<a<<endl;
    }
    virtual void show3(){
        cout<<a<<endl;
    }
};

// 修正后的函数
void callShow2(Base* x){
    x->show2();
}

int main() {
    Derived b ; 
    b.show1();
    callShow2(&b); // 调用修正后的函数来展示 show2 的效果
    return 0;
}

汇编

__cxx_global_var_init:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        lui     a0, %hi(std::__ioinit)
        addi    a0, a0, %lo(std::__ioinit)
        sw      a0, -12(s0)
        call    std::ios_base::Init::Init() [complete object constructor]
        lw      a1, -12(s0)
        lui     a0, %hi(_ZNSt8ios_base4InitD1Ev)
        addi    a0, a0, %lo(_ZNSt8ios_base4InitD1Ev)
        lui     a2, %hi(__dso_handle)
        addi    a2, a2, %lo(__dso_handle)
        call    __cxa_atexit
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

callShow2(Base*):
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 0(a0)
        lw      a1, 0(a1)
        jalr    a1
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

main:
        addi    sp, sp, -48
        sw      ra, 44(sp)
        sw      s0, 40(sp)
        addi    s0, sp, 48
        mv      a0, zero
        sw      a0, -36(s0)
        sw      a0, -12(s0)
        addi    a0, s0, -32
        sw      a0, -40(s0)
        call    Derived::Derived() [base object constructor]
        lw      a0, -40(s0)
        call    Base::show1()
        lw      a0, -40(s0)
        call    callShow2(Base*)
        lw      a0, -36(s0)
        lw      s0, 40(sp)
        lw      ra, 44(sp)
        addi    sp, sp, 48
        ret

Derived::Derived() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        sw      a0, -16(s0)
        call    Base::Base() [base object constructor]
        lw      a1, -16(s0)
        lui     a0, %hi(vtable for Derived)
        addi    a0, a0, %lo(vtable for Derived)
        addi    a0, a0, 8
        sw      a0, 0(a1)
        addi    a0, zero, 3
        sw      a0, 12(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::show1():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::Base() [base object constructor]:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a1, -12(s0)
        lui     a0, %hi(vtable for Base)
        addi    a0, a0, %lo(vtable for Base)
        addi    a0, a0, 8
        sw      a0, 0(a1)
        addi    a0, zero, 1
        sw      a0, 4(a1)
        addi    a0, zero, 2
        sw      a0, 8(a1)
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Derived::show2():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Derived::show3():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

Base::show2():
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        sw      a0, -12(s0)
        lw      a0, -12(s0)
        lw      a1, 4(a0)
        lui     a0, %hi(_ZSt4cout)
        addi    a0, a0, %lo(_ZSt4cout)
        call    std::ostream::operator<<(int)
        lui     a1, %hi(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        addi    a1, a1, %lo(_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
        call    std::ostream::operator<<(std::ostream& (*)(std::ostream&))
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

_GLOBAL__sub_I_example.cpp:
        addi    sp, sp, -16
        sw      ra, 12(sp)
        sw      s0, 8(sp)
        addi    s0, sp, 16
        call    __cxx_global_var_init
        lw      s0, 8(sp)
        lw      ra, 12(sp)
        addi    sp, sp, 16
        ret

std::__ioinit:
        .zero   1

vtable for Derived:
        .word   0
        .word   typeinfo for Derived
        .word   Derived::show2()
        .word   Base::show1()
        .word   Derived::show3()

typeinfo name for Derived:
        .asciz  "7Derived"

typeinfo name for Base:
        .asciz  "4Base"

typeinfo for Base:
        .word   _ZTVN10__cxxabiv117__class_type_infoE+8
        .word   typeinfo name for Base

typeinfo for Derived:
        .word   _ZTVN10__cxxabiv120__si_class_type_infoE+8
        .word   typeinfo name for Derived
        .word   typeinfo for Base

vtable for Base:
        .word   0
        .word   typeinfo for Base
        .word   Base::show2()
        .word   Base::show1()

行为分析

首先观察表,子类是肯定包含了父类的所有虚函数的,只是会把重新实现的,替换为自己的,所以体现多态就是这样,我们传入参数是基类指针,因为默认的虚函数表是在首地址的,大家都一样,然后我们都想调用show2(),因为穿进来的指针指向的地址拿到的虚函数表是不一样的,虽然偏移一样,但是最后调用的就是不同的虚函数实现。

为什么构造函数不能是虚函数

由之前的行为分析知道,子类实例化过程中,会去调用父类的构造函数,将对象的首地址设置为父类的虚函数表,再去设置父类的成员变量,再退回到子类构造函数重复一样的操作。
对于虚函数,是为了覆盖父类的行为实现多态,那么假设构造是虚函数,怎么去覆盖父类的构造行为,虚函数的;
进一步将,子类的行为是,调用父类构造,然后覆盖他的虚函数表,然后父类构造变成了子类构造,这完全乱套。
所以来说,构造根本就和多态不是一个东西,混在一起完全没有意义,他只是帮助设置初值和虚函数表的,与多态行为无关。


http://www.kler.cn/a/284823.html

相关文章:

  • C语言第九周课——经典算法
  • Ubuntu20.4系统编译瑞芯微RK3568 SDK
  • 内置RTK北斗高精度定位的4G执法记录仪、国网供电服务器记录仪
  • C 语言标准库 - <errno.h>
  • 鸿蒙华为商城APP案例
  • 力扣--树题总结
  • 【Go语言成长之路】使用 Go 和 Gin 开发 RESTful API
  • 五,Spring Boot中的 Spring initializr 的使用
  • go.uber.org/ratelimit 源码分析
  • MyBatis一级缓存和二级缓存以及 mybatis架构
  • .net开发日常笔记(持续更新)
  • 续:MySQL的并行复制
  • XtQuant是什么?哪家券商支持miniQMT,XtQuant?
  • 使用SQLite进行Python简单数据存储的线程安全解决方案
  • Centos服务器配置使用密钥登录
  • 【C++题解】1722 - 输出两位的巧数
  • Docker 部署 Kafka 可视化 Kafka-UI
  • Arco Voucher - 不知道有什么用的凭证单据录入表单插件
  • 简易STL实现 | Deque的实现
  • PyMOL的开源版和商业版如何选择 PyMOL开源版安装 PyMOL商业版安装 PyMOL安装教程 远程安装PyMOL正式版 官网版
  • PDF文本指令解析与文本水印去除
  • 【IDEA】一键重启多个服务
  • 游戏出海,燃动全球,“安全”如何通关?
  • 【C++】有关vector迭代器失效问题
  • 快速了解Git服务器端基础及基本操作命令(一)
  • mysql的group by怎么用