1.1 问题一
1.1.1 new 和malloc 的区别
- new 关键字是C++的一部分
- malloc是由C库提供的
函数
(如果没有C库就不能申请内存空间) - new 是以具体类型为单位进程内存分配
- malloc 以字节为单位进程内存分配
- new 在申请内存空间的时候可进行初始化
- malloc 仅仅根据需要申请定量的内存空间
1.1.2 实例代码
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
cout<<"Test::Test()"<<endl;
}
};
int main()
{
Test * p1= new Test;
Test * p2 =(Test*) malloc(sizeof(Test));
return 0;
}
运行结果
通过运行结果可以看出,构造函数仅仅被调用了一次,说明是new进行了初始化,malloc仅仅是分配了空间,并不进行初始化。
1.1.3 delete 和free 的区别
using namespace std;
class Test
{
int* mp;
public:
Test()
{
cout << "Test::Test()" << endl;
mp = new int(100);
cout << *mp << endl;
}
~Test()
{
delete mp;
cout << "~Test::Test()" << endl;
}
};
int main()
{
Test* pn = new Test;
Test* pm = (Test*)malloc(sizeof(Test));
free( pn); //虽然可以释放new 申请的内存,但是不会调用析构函数,不会释放mp 申请的资源,导致内存泄漏
delete(pm); //pm指向的并不是一个合法的对象,调用delete可能会导致错误的产生
return 0;
}
1.2 问题二
1.2.1 构造函数是否可以成为虚函数?
- 构造函数不可能成为虚函数,构造函数执行结束以后,虚函数表指针才被正确的初始化
1.2.2 析构函数是否可以成为虚函数?
析构函数可以成为虚函数,因为析构函数是在对象销毁前调用的,虚函数表指针是正确的指向虚函数表的,建议设计类时将析构函数声明为虚函数。
1.2.3案例分析
//为什么建议将析构函数声明为虚函数。
#include <iostream>
using namespace std;
class Parent
{
public:
Parent()
{
cout<<"Parent()"<<endl;
}
~Parent()
{
cout<<"~Parent()"<<endl;
}
};
class Child:public Parent
{
public:
Child()
{
cout<<"Child()"<<endl;
}
~Child()
{
cout<<"Child()"<<endl;
}
};
int main()
{
Parent * p = new Child;
delete p;
return 0;
}
运行结果:
分析结果:在main函数中父类指针指向了子类对象,在销毁对象的时候,我们期望销毁的是子类对象,但是从结果来看,编译器销毁的是父类对象,那该怎么办?将析构函数声明为虚函数就可以了。所以建议在编程的时候将析构函数声明为虚函数。
1.2.4
构造函数中(内部
)不可能发生多态,因为在构造函数执行的时候,虚函数表指针未被正确初始化
析构函数中((内部
))不可能发生多态行为,在析构函数执行的时候,虚函数表指针已经被销毁。
构造函数中调用的虚函数必定是当前类中定义的版本
- 构造函数和析构函数中不能发生多态行为,只调用当前类中定义的函数版本。
1.3 问题三
1.3.1 继承中如何使用强制类型转换
- dynamic_cast 是与继承相关的
类型转换关键字
- dynamic_cast要求相关的类中必须有
虚函数
- 用于有直接或间接继承关系的指针(引用)之间
(1)指针: 转换成功:得到目标类型的指针,转换失败:得到一个空指针
(2) 引用:转换成功:得到目标类型的引用,转换失败:得到一个异常的操作信息。
1.3.2 示例
class Parent
{
public:
Parent()
{
cout<<"Parent()"<<endl;
}
virtual ~Parent()
{
cout<<"~Parent()"<<endl;
}
};
class Child : public Parent
{
};
int main()
{
Parent * p = new Child;
Child* c = dynamic_cast<Child*>(p);
if(c != NULL)
{
cout<<"c =" <<c<<endl;
}
else
{
cout <<"cast error" <<endl;
}
cout<<endl;
Parent * p2 = new Parent;
Child* c2 = dynamic_cast<Child*>(p2);
if(c2 != NULL)
{
cout<<"c =" <<c2<<endl;
}
else
{
cout <<"cast error" <<endl;
}
return 0;
}
- 结果
参考一 :狄泰软件学院C++进阶剖析
参考二 : C++ primer中文版