当前位置:   article > 正文

静态成员函数、内联函数、构造函数、析构函数、operator=是否可以定义为虚函数?_静态成员函数和内联函数不能是虚函数,友员函数和构造函数也不能是虚函数,但是析构

静态成员函数和内联函数不能是虚函数,友员函数和构造函数也不能是虚函数,但是析构

1.静态成员函数:静态成员函数属于类,也属于对象,但最终属于类,在内存中只有一份,即没有this指针;而虚函数必须根据指向哪一个对象来确定调用谁的虚函数,即虚函数要在有对象的基础上才可以。所以静态成员函数不可以定义为虚函数。
2.内联函数:由于内联函数是直接展开代码,并不存在函数调用,即没有函数地址,那么就不能存在虚表中,所以内联函数不可定义为虚函数;
3.构造函数:虚表指针是存储在对象的内存空间,当调虚函数时,是通过虚表指针指向的虚表里的函数地址进行调用的。如果将构造函数定义为虚函数,就要通过虚表指针指向的虚表的构造函数地址来调用。而构造函数是实例化对象,定义为虚函数后,对象空间还没有实例化,那就没有虚表指针,自然无法调用构造函数,那构造函数就失去意义,所以不能将构造函数定义为虚函数。
4.析构函数:最好将基类的析构函数定义为虚函数。

  1. class Person
  2. {
  3. public:
  4. ~Person()
  5. {
  6. cout << "~Person()" << endl;
  7. }
  8. protected:
  9. string _name;
  10. };
  11. class Student: public Person
  12. {
  13. public:
  14. ~Student()
  15. {
  16. free(_num);
  17. cout << " ~Student()" << endl;
  18. }
  19. protected:
  20. string _num;
  21. };
  22. int main()
  23. {
  24. Person *p = new Student(); // 开Student类的空间,call子类构造函数,基类指向这段空间
  25. delete p; //先析构,再free
  26. system("pause");
  27. return 0;
  28. }

因为delete p :调析构函数是普通函数调用,普通函数调用和对象类型有关,p的对象类型是Person,那就会调基类的析构函数,即没有调子类的析构函数。那么子类的_num就会没有free,从而造成内存泄漏。
如果将基类析构函数定义为虚函数:

  1. virtual ~Person()
  2. {
  3. cout << "~Person()" << endl;
  4. }
  5. ~Student() //子类可以不加virtual ,也可以构成多态
  6. {
  7. cout << "~Student()" << endl;
  8. }
  9. //析构函数的重写是特例,基类和派生类析构函数在编译阶段被处理成相同函数名(destructor)

因为Person *p = new Student();而p指向子类Student 的对象,析构是虚函数,就会掉Student的析构函数,而子类的析构函数又自动调了父类的析构函数,这样就不会造成资源泄漏等问题。
5.operator=:虽然可以把operator=定义为虚函数(返回值不同,可以构成协变),但最好不要将operator=定义为虚函数,因为使用时容易引起混淆且没有意义。
6.不要在构造函数和析构函数中调用虚函数。
因为在构造函数中,对象还不完整,所以虚表指针可能还没初始化好,那么调用虚函数,就会发生未定义行为;
因为在析构函数中,会将对象某些成员清理,那么对象也不完整,同理,会发生未定义行为。
--------------------- 
作者:sophia__yu 
来源:CSDN 
原文:https://blog.csdn.net/sophia__yu/article/details/82796841 
版权声明:本文为博主原创文章,转载请附上博文链接!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/731449
推荐阅读
相关标签
  

闽ICP备14008679号