C++中常见的一些小问题总结(一)
1.类的构造函数过程,如何让类实例化时,不调用构造函数(或类destroy的时候不调用析构函数)?
首先,我们要知道知道类的构造函数的作用是什么,当然很多人会说是在里面进行类的初始化的,没错,但是很多人弄清楚类的基本资源申请也是由他完成的,这里不得不提到一组关键字:new/delete与malloc/free,你可能已经注意到我的说法,是关键字而不是称呼他们为函数,因为他们是完全不同的概念。前者是C++的运算符,后者才是C/C++的标准库函数。
其次,这两组数是有区别的,虽然我们一般不会去过分关注,至少我在使用的时候更偏向于new和delete。其实,它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
于是,我们又有些映像,好像new[]和delete[]的时候,那他们又与上面的new和delete有什么区别呢?
int *p= new int[2];
delete []p;//这里调用的过程是先析构p[0],然后再析构释放p[1];
这里就是他们的区别,当new的对象是一个数组时,系统维护的自然就是这个对象的数组指针,当我们delete p时,其实只是释放了p[0],其他指针对象则会变成引起程序bug的野指针。
2.对于第二个问题,当然你现在已经明白该如何去解答了,其实就是让malloc吧类中构造函数该干的基本任务(申请内存)给干了,那析构函数自然就没有运行的意义了,那么下面就来完成这个想法的实验吧:
class A{
public A(){cout<<"A constructed now!"<<endl;}
void pout0(){
cout<<"A pout"<<endl;
}
};
class B:A{
public B(){cout<<"B xxxx";}
void pout(){cout<<"B fuction works!"<<endl;}
};
void main(){
B* p=(B*) malloc(sizeof(B));
p->pout;
}
输出结果为:B function works!这里的A构造函数和B构造函数就被屏蔽了。
3.如果你想通过p来调用A中的函数pout0(),是否可以使用p呢,答案是肯定的,只是要注意类继承的属性到底是私有的还是共有的,前者的父类访问权限是有限制的,所以你需要对子类的继承做修改即可。
以上就是一点小小的总结,以后会继续的,欢迎各位讨论交流,才开始写博和分享,主要是有些时间。谢谢各位指点~