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

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

posted @ 2019-12-07 10:32  人民广场的二道贩子  阅读(120)  评论(0编辑  收藏  举报