• C++ 类和虚函数


    构造函数和析构函数可以是虚函数吗

    虚函数的调用通过虚表指针来指定,虚表指针包含在对象的内存空间中,它在构造函数调用后完成初始化;

    析构函数可以且常常是虚函数

    这个原理上就很好理解啦,因为此时 vtable 已经初始化了,完全可以把析构函数放在虚函数表里面来调用。

    C++类有继承时,析构函数必须为虚函数。如果不是虚函数,则使用时可能存在内存泄漏的问题。

    虚表存放在哪里

    C++ 虚函数表及多态内部原理详解(一)

    虚表是全局唯一的,放在全局数据区;

    虚函数和纯虚函数区别

    知乎-C++ 虚函数、纯虚函数

    对象的内存大小计算

    C++类所占内存大小计算_大副的博客-CSDN博客

    空类,大小占用为1;

    有虚函数,虚表指针占用为4;

    非static数据成员的占用;

    需要考虑内存对齐的问题;

    类的基本成员函数

    默认构造函数;

    析构函数;

    赋值运算符重载;

    拷贝构造函数;

    基类和派生类,基类指针指向派生类对象

    基类指针可以指向派生类对象,其中句柄类型也就是指针类型决定哪个类的函数被调用,如果是基类指针指向派生类,那么调用的函数还是基类的;

    但是,如果有了virtual以后,调用哪个版本的virtual函数则由句柄指向的对象来决定;也就是虽然指向的还是句柄,但是句柄仍然会指向派生类对象的虚表

    如下所示,使用基类D指向派生类E,在创建时调用E的构造函数,然后递归调用基类构造函数;在销毁时,调用D的析构函数,然后递归调用基类的析构函数;

    1. #include <iostream>
    2. using namespace std;
    3. // 基类和派生类的析构函数
    4. class C{
    5. public:
    6. C(){
    7. cout << "C constructor\n";
    8. }
    9. ~C(){
    10. cout << "C deconstructor\n";
    11. }
    12. };
    13. class D: public C{
    14. public:
    15. D(){
    16. cout << "D constructor\n";
    17. }
    18. ~D(){
    19. cout << "D deconstructor\n";
    20. }
    21. };
    22. class E:public D{
    23. public:
    24. E(){
    25. cout << "E constructor\n";
    26. }
    27. ~E(){
    28. cout << "E deconstructor\n";
    29. }
    30. };
    31. int main(){
    32. D* test = new E();
    33. delete test;
    34. return 0;
    35. }
    36. C constructor
    37. D constructor
    38. E constructor
    39. D deconstructor
    40. C deconstructor

    如果析构函数是虚函数,则结果如下: 

    1. #include <iostream>
    2. using namespace std;
    3. // 基类和派生类的析构函数
    4. class C{
    5. public:
    6. C(){
    7. cout << "C constructor\n";
    8. }
    9. virtual ~C(){
    10. cout << "C deconstructor\n";
    11. }
    12. };
    13. class D: public C{
    14. public:
    15. D(){
    16. cout << "D constructor\n";
    17. }
    18. ~D(){
    19. cout << "D deconstructor\n";
    20. }
    21. };
    22. class E:public D{
    23. public:
    24. E(){
    25. cout << "E constructor\n";
    26. }
    27. ~E(){
    28. cout << "E deconstructor\n";
    29. }
    30. };
    31. int main(){
    32. D* test = new E();
    33. delete test;
    34. return 0;
    35. }
    36. C constructor
    37. D constructor
    38. E constructor
    39. E deconstructor
    40. D deconstructor
    41. C deconstructor

  • 相关阅读:
    c++图论
    Java版本spring cloud + spring boot企业电子招投标系统源代码
    纯前端实现 导入 与 导出 Excel
    get_trade_detail_data函数使用
    pytorch使用cat()和stack()拼接tensors
    【DCMTK】DcmItem::putAndInsertOFStringArray失败
    Linux Spug自动化运维平台公网远程访问---内网穿透
    针对边缘计算,红帽企业Linux 9有哪些新功能?
    面试经典sql(大数据):同时在线人数
    Win10安装node-sass
  • 原文地址:https://blog.csdn.net/qq_36383623/article/details/109261729