zoukankan      html  css  js  c++  java
  • 第55课.经典问题解析四

    1.关于动态内存分配

    newmalloc的区别是什么?
    deletefree的区别是什么?

    new关键字与malloc函数的区别:
    a.
     new关键字是c++的一部分
     malloc是由c库提供的函数

    b.
     new以具体类型为单位进行内存分配
     malloc以字节为单位进行内存分配

    c.
    new在申请内存空间时可以进行初始化(临时对象)
    malloc仅根据需要需要申请定量的内存空间

    d.
    new能够触发构造函数的调用
    malloc仅分配需要的内存

    e.
     对象的创建只能选择new,不能选择malloc(不能触发构造函数)

    delete和free的区别

    a.
     delete关键字是c++的一部分
     free是由c库提供的函数

    b.
    delete能够触发析构函数的调用
    free仅归还之前分配的内存空间

    c.
     对象的销毁只能使用delete,不能选择free

    eg:

    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    class Test
    {
    public:
        Test()
        {
            cout << "Test::Test()" << endl;
        }
        
        ~Test()
        {   
            cout << "~Test::Test()" << endl;
        }
    };
    
    int main()
    {
        Test* pn = new Test;        // 分配内存空间(new Test),同时初始化这段内存
                                    // 空间Test对象(临时对象)
                                    // new能触发构造函数
        Test* pm = (Test*)malloc(sizeof(Test));     //仅仅分配一段空间
        
        delete pn;        // delete能够触发析构函数
        free(pm);
        
        return 0;
    }
    

    2.关于虚函数

    构造函数是否可以成为虚函数?
    析构函数是否可以成为虚函数?

    答案:

    a.构造函数不可能成为虚函数
     在构造函数执行过程中,虚函数表未被正确初始化。此时定义虚函数,使用虚函数表,必然错误。
     在构造函数执行结束后,虚函数表指针才会被正确初始化

    b.析构函数可以成为虚函数
     析构函数在对象销毁前被调用,此时虚函数指针是正确的指向虚函数表的
     建议在设计类时将析构函数声明为虚函数

    eg:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Base
    {
    public:
        Base()
        {
            cout << "Base()" << endl;
            
            func();
        }
        
        virtual void func() 
        {
            cout << "Base::func()" << endl;
        }
        
        //virtual ~Base()
        ~Base ()        
        {
            func();
            
            cout << "~Base()" << endl;
        }
    };
    
    
    class Derived : public Base
    {
    public:
        Derived()
        {
            cout << "Derived()" << endl;
            
            func();
        }
        
        virtual void func()
        {
            cout << "Derived::func()" << endl;
        }
        
        ~Derived()
        {
            func();
            
            cout << "~Derived()" << endl;
        }
    };
    
    
    int main()
    {
        Base* p = new Derived();
        
        // ...
        
        delete p;           // 当析构函数未被定义为 virtual 时 delete p根据指针到类型来调用析构函数
                            // 此时只会调用父类的析构函数。而不会调用子类的析构函数。错误
                            // 当使用虚函数时,构成多态。此时编译器会根据p所指的实际对象来决定析构的调用
        
        return 0; 
    }
    

    ===
    构造函数中是否可以发生多态?

    析构函数中是否可以发生多态?

    答案:

    a.构造函数中不可能发生多态行为
     在构造函数执行时,虚函数表指针为被正确初始化

    b.析构函数中不可能发生多态行为
     在析构函数执行时,虚函数表指针已经被销毁
    (这里注意,析构函数能被定义为虚函数。是因为调用虚函数时,虚函数表指针,还是健全的。
    但是当析构函数被执行时,虚函数表指针就被销毁了,此时就无法使用虚函数来实现多态了)

    注:构造函数和析构函数中不能发生多态行为,只能调用当前类中定义的函数版本

  • 相关阅读:
    MySql 5.6以下版本自定义函数返回VARCHAR的中文问题
    解决Tomcat的java.lang.IllegalStateException: Cannot create a session after the response has been committed问题
    Lucene自定义规则范围查询
    JS吊炸天的代码
    又是正则
    JS显示指定字符数,避免一个中文两个字符的情况
    PostgreSql查看当前表的主外键关系
    java基础(个人学习笔记) A
    Elasticsearch5.5.1插件开发指南
    ElasticSearch5.5.1插件分类
  • 原文地址:https://www.cnblogs.com/huangdengtao/p/11996561.html
Copyright © 2011-2022 走看看