多态/虚函数/虚函数表

OVERVIEW

  • 多态/虚函数/虚函数表
      • 1.虚函数引入后类发生的变化?
      • 2.虚函数表的生成时机和生成原因?
      • 3.虚函数表指针赋值的时机?
      • 4.类对象在内存中的布局?
      • 5.虚函数的工作原理和多态性的体现?
      • 6.其他问题

多态/虚函数/虚函数表


  • non-virtual:不希望derived class 重新定义该它
  • virtual:希望derived class重新定义它,并且你对它已经有了默认的定义
  • pure-virtual:希望derived class一定要重新定义它

1.虚函数引入后类发生的变化?

class A {
public:
    void func1() {}
    void func2() {}
public:
    virtual void vfunc() {}
};
sizeof(A) = 4;//x86
sizeof(A) = 8;//linuxgcc

当一个或者多个虚函数加入到类中之后,编译器会向类中插入一个看不见的成员变量void *vptr虚函数表指针(virtual table ptr),

2.虚函数表的生成时机和生成原因?

当某个类中存在至少一个虚函数的时候,在编译期间编译器就会为类A生成一个虚函数表 vtbl(virtual table),

虚函数表会一直伴随着类经过编译、链接、生成可执行文件、装载到内存中来,

3.虚函数表指针赋值的时机?

多态/虚函数/虚函数表_第1张图片

对于有虚函数的类在编译期时编译器向类的构造函数中安插为vptr赋值的语句,在创建类对象时使得vptr指向类的vtbl,

4.类对象在内存中的布局?

class A {
public:
    void func1() {}
    void func2() {};
public:
    virtual void vfunc1() {}
    virtual void vfunc2() {}
    virtual ~A() {}
private:
    int m_a;
    int m_b;
};
sizeof(A) = 12;

多态/虚函数/虚函数表_第2张图片

类A在内存中的布局:

5.虚函数的工作原理和多态性的体现?

多态性:多态必须存在虚函数,没有虚函数绝不可能存在多态,并且只有调用虚函数时才有存在多态性的可能,

多态/虚函数/虚函数表_第3张图片

从代码上看多态的体现

  1. 父类中有虚函数、子类中也有该同名的虚函数,
  2. 当通过父类指针new子类对象 or 通过父类引用绑定子类对象时,
  3. 如果用父类指针来调用该虚函数,那么调用的是子类的虚函数,
class Base {
public:
    virtual void myvirfunc() {}
};

Base *ptr = new Base();
ptr->myvirfunc();//多态
Base base;
base.myvirfunc();//非多态
Base *pbase = &base;
pbase->myvirfunc();//多态

从表现形式上看多态的体现

  1. 程序中既存在父类也存在子类,父类中必须含有虚函数,子类中也必须重写父类中的虚函数,
  2. 父类指针指向子类对象,或者父类引用绑定/指向子类对象,
  3. 当通过父类的指针or引用,调用子类中重写的虚函数时,就能看出多态性的表现了(调用的是子类的虚函数),
class Derive : public Base {
public:
    virtual void myvirfunc();
};
//父类指针指向子类对象1
Derive derive;
Base *pbase1 = &derive;
pbase1->myvirfunc();
//父类指针指向子类对象2
Base *pbase2 = new Derive();
pbase2->myvirfunc();
//父类引用绑定子类对象
Derive derive2;
Base &refer_base = derive2;
refer_base.myvirfunc();

多态/虚函数/虚函数表_第4张图片

6.其他问题

  • 问:当进行多重继承时,子类对象有几个虚函数表指针?子类有几个虚函数表?
  • 答:在进行多重继承时,子类对象会包含每个父类的成员变量和虚函数表指针。

如果每个父类都有虚函数,那么每个父类都会有一个虚函数表,子类对象会包含每个父类的虚函数表指针,因此子类对象会有多个虚函数表指针,每个指针指向相应的虚函数表。

如果某个父类没有虚函数,那么子类对象就不会包含该父类的虚函数表指针,只会包含其他父类的虚函数表指针和成员变量。

  • 问:如果将虚继承(虚基类)融入进来,这时又多出来了虚基类表指针和虚基类表,那么虚基类表指针在对象内存中的布局?
  • 浅谈C++类中的内存布局:https://www.zhihu.com/tardis/zm/art/380147337?source_id=1005

你可能感兴趣的:(查缺补漏C++,c++)