C++虚函数原理及其使用限制

来源:互联网 发布:msp430单片机价格 编辑:程序博客网 时间:2024/06/05 19:11
  • 虚函数的原理
    默认情况下,子类的数据表中有一个虚函数表指针,其保存着虚函数表的地址。
    一般情况下,子类没有重写父类的成员函数,则子类的虚函数表指针指向的是父类的虚函数表。
    若子类中有重写父类的成员函数,则子类中的虚函数表指针会重新定向到自己的虚函数表的位置,因此执行的虚函数位置也是子类的虚函数位置。
    只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。那么对于在派生类的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了(语法上可加可不加,不加的话编译器会自动加上,但为了阅读方便和规范性,建议加上)。
    Shape OxCCFF vftable_ptr m_iEdge calcArea_ptr calcArea()
  • 虚函数的使用限制
    • 普通函数不能是虚函数
      virtual int test()
    • 不能修饰静态成员函数,因为成员函数实例相关,静态函数类相关。虚函数,是一种特殊的成员函数,用来实现运行时多态的。所以静态函数不可能是虚函数。
      class Animal public: virtual static int getCount();
    • 不能修饰内联函数,编译会通过,但是编译时会忽略内联函数,内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数。
      class Animal public: inline virtual int eat()
    • 不能修饰构造函数,同样是因为在编译时会进行构造函数,而动态多态不是
      class Animal public: virtual Animal()
  • 覆盖和隐藏
    覆盖,没有学习多态时,父类和子类有重名的成员函数(动态多态),此时称为覆盖。
    隐藏,如果没有在子类中定义同名的虚函数,那么在子类的虚函数表中就会写上父类相应的虚函数入口地址
  • 如果在子类中定义了同名的虚函数,那么在子类的虚函数表就会把原来指向父类的函数指针保存的地址覆盖为指向子类虚函数的函数地址,因此执行完子类的析构函数会执行父类的析构函数
  • 一些概念
    • 对象大小,类声明结束后其中数据成员占用的内存大小
    • 对象地址,实例化一个类会占用一定量的内存单元,内存
    • 对象成员地址,实例化一个对象成员之后,可能会有一个或多个数据成员,每一个数据成员所占据的地址,对象每一个数据成员由于数据类型的不同,因此占的内存大小也不同,对应的地址也不同
    • 虚函数表指针,有虚函数的情况下,在实例化的时候,对象的第一块内存所存储的是指针,该指针为虚函数表的指针,因此占据的内存大小为4
    • 对于没有任何数据成员的类,实例化之后,会占用一个空内存单元来证明自己的存在
    • 在有虚函数的情况下,每实例化一个类,第一个存储单元内存的是虚函数的入口地址,第二个存储单元则是数据成员

原创粉丝点击