zoukankan      html  css  js  c++  java
  • 构造析构与虚函数

    new/delet    是C++编译器实现的关键字,以类型为单位分配,申请时可以初始化内存

    malloc/free  是C库实现的函数,以字节为单位分配,并不会初始化内存

    #include <iostream>
    #include <string>
    #include <cstdlib>
    
    using namespace std;
    
    class superclass
    {
    public:
        superclass()
        {  cout << "superclass constructor" << endl; }
        virtual ~superclass()
        {  cout << "superclass destructor" << endl;  }
    };
    
    class subclass : public superclass
    { 
    
    };
    
    int main()
    {
        subclass* p_sub = new subclass;                              // 会触发构造函数
        subclass* p_sub_1 = (subclass *) mallloc(sizeof(subclass));  // 不会触发构造函数
        
        subclass* p_sub_2 = dynamic_cast<subclass*>(p_sub); 
        
        delete p_sub;   // 会触发析构函数
        free(p_sub_1);  // 不会触发析构函数
        
        return 0;
    }

     构造函数不可能成为虚函数:在构造函数执行完后,虚函数表和虚函数表指针才会初始化。

     析构函数可以成为虚函数:尽量将析构函数声明为虚函数。(当定义指向子类的父类指针后,再delete父类指针时,子类的析构函数函数也会被调用,避免了内存泄漏。尽量把析构函数声明为虚函数)

     构造函数不可以发生多态行为:在构造函数之前,虚函数表指针还未初始化。

     析构函数不可以发生多态行为:在析构函数之前,虚函数表指针就被销毁。

    构造函数和析构函数:调用当前类定义的虚函数,并不会发生多态的行为

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class superclass
    {
    public:
        superclass()   // 不可以声明为虚函数
        {       
            func();  // 构造函数中调用虚函数,不会发生多态,运行本类中的虚函数
        }
        virtual void func() 
        {
            cout << "superclass virtual function" << endl;
        }   
        virtual ~superclass()  // 尽量将析构函数声明为虚函数,防止未被调用而造成内存泄漏
        {
            func();  // 析构函数中调用虚函数,不会发生多态,运行本类中的虚函数
        }
    };
    
    
    class subclass : public surperclass
    {
    public:
        subclass()
        { 
            func();
        }
        virtual void func()
        {
            cout << "subclass virtual function" << endl;
        }
        ~subclass()
        {
            func();
        }
    };
    
    
    int main()
    {
        superclass* p_super = new subclass();
           
        delete p_super;  

    // 如果superclass 的虚构函数没有声明为虚函数,编译器会根据p_super的类型(superclass)调用superclass的析构函数,不会调用subclass的析构函数 // 当superclass的虚函数声明为虚函数,编译器会根据p_super指向的对象(subclass)来先调用subclass的析构函,再调用superclass的析构函数。 return 0; }

    继承中的强制类型转换:

    dynamic_cast用于有直接或间接继承关系的类的指针或引用之间的强制转换。

    dynamic_cast要求:相关类中必须有虚函数,

    指针:转换成功-->得到目标类型的指针。转换失败-->得到空指针。

    引用:转换成功-->得到目标类型的应用。转换失败-->得到异常操作信息。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class superclass
    {
    public:
        superclass()
        {
            cout << "superclass constructtor" << endl;
        }
        virtual ~superclass()  // 为了使用 dynmaic_cast 而声明成虚函数
        {
            cout << "superclass destructor" << endl;
        }
    };
    
    class subclass : public superclass
    {
    
    };
    
    int main()
    {
        superclass* p_super1 = new superclass;  
        subclass* p_sub1 = dynamic_cast<subclass*>(p_super1); // 不能用子类的指针指向父类,dynmaic_cast返回空指针
       
        superclass* p_super2 = new subclass;                
        subclass* p_sub2 = dynamic_cast<subclass*>(p_super2); // 不能用父类指针初始化子类指针,通过 dynamic_cast返回正确地址
        
        delete p;
        
        return 0;
    }

      

  • 相关阅读:
    对于想用OS但又觉得单片机资源太过紧张,状态机是个不错的选择分享一种状态机设计方法
    状态机实践入门
    Codewarrior 调试错误ILLEGAL_BP
    坑爹的AVR编译器中文路径问题
    跨入AVR
    atmega8 例程:USART串口通信
    2011总结
    atmega8 默认内部RC振荡 + 解锁
    关于AVR I/O 的驱动能力的介绍
    atmega8 例程:系统库函数的延迟
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10856860.html
Copyright © 2011-2022 走看看