第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

include

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

include

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  人民广场的二道贩子  阅读(143)  评论(0)    收藏  举报