operator new之被Drived Class继承
来源:互联网 发布:矩阵的点乘 编辑:程序博客网 时间:2024/05/06 12:55
对于operator new操作符有一个容易被忽略的特性:
operator new成员函数会被derived class继承!
定制operator new的一个常见理由就是为了针对所在class的对象分配行为提供最优化,而不是为了其derived class。
下面先讲解下CBase *base = new CBase();的都执行了哪些接口:
step1:
如果定制了CBase::operator new,则调用CBase::operator new
如果没有定制CBase::operator new,则调用系统提供的::operator new
调用形式为:
void* buf = operator new( sizeof(CBase) )
buf用来存储CBase对象
step2:
调用构造函数CBase()在step1申请的buf堆空间上创建CBase对象初始化buf内存。
step3:如果delete base
如果定制了CBase::operator delete,则调用CBase::operator delete
如果没有定制CBase::operator delete,则调用系统标准操作符::operator new
调用形式为:
operator delete( buf ); //buf时step1申请的为了保存CBase对象的堆内存buf
由上可知,如果CBase定制了operator new,权限为public或protected可以被CDerived类继承。
则下面讲解下CDerived *derived = new CDerived();都执行了哪些接口
step1:
调用CBase::operator new
调用形式为:
void* buf = CBase::operator new( sizeof (CDerived) );
buf用来存储CDerived对象
step2:
调用构造函数CDerived()在step1申请的buf堆空间上创建CDerived对象初始化buf内存。
step3:如果delete derived
如果定制了CBase::operator delete,则调用CBase::operator delete
如果没有定制CBase::operator delete,则调用系统标准操作符::operator new
调用形式为:
operator delete( buf ); //buf时step1申请的为了保存CDerived对象的堆内存buf
以上行为都可以通过程序来测试,并验证其正确性,验证代码如下所示:
#include <stdio.h>#include <stdlib.h>#include <string>#include <iostream>class CBase{public:CBase(){}~CBase(){}void setAge(int age){m_age = age;}void* operator new(std::size_t size){if (size == 0){size = 0;}printf("%s:%d:CBase:%s, (new size, class size):(%zu, %zu)\n", __FILE__, __LINE__, __FUNCTION__, size, sizeof(CBase));void* buf = malloc(size);printf("%s:%d:CBase:%s, buf:%p\n", __FILE__, __LINE__, __FUNCTION__, buf);return buf;}void operator delete(void* buf){if (buf == NULL){return;}printf("%s:%d:CBase:%s, buf:%p\n", __FILE__, __LINE__, __FUNCTION__, buf);free(buf);return;}private:int m_age;};class CDerived : public CBase{public:CDerived(){printf("%s:%d:CDerived:%s, sizeof(class CDerived):%zu\n", __FILE__, __LINE__, __FUNCTION__, sizeof(CDerived));}~CDerived(){printf("%s:%d:CDerived:%s\n", __FILE__, __LINE__, __FUNCTION__);}void setWeight(int w){m_weight = w;}private:int m_weight;};int main(){printf("\n===============new CBase()======================\n");CBase* base = new CBase();delete base;printf("================================================\n\n");printf("***************new CDerived()**********************\n");CDerived* derived = new CDerived();delete derived;printf("***************************************************\n\n");return 0;}
测试结果如下所示:
可知new CDerived()时先调用了基类的CBase::operator new操作符,入参为自己的类大小sizeof(CDerived),
然后调用了自己的构造函数CDerived(),在delete derived时调用了自己的析构函数~CDerived(),最后调用了基类的CBase::operator delete来释放保存derived的堆内存buf。
如果CDerived不定制自己的operator new,如果用CBase的operator new来分配保存自己对象derived的堆内存,在delete时还是调用CBase的operator new来释放保存自己对象derived的堆内存。
这就是CBase定制的operator new只是特定大小sizeof(CBase)的对象申请空间,如果CBase的operator new被一直继承下去,有可能会被用来为CDerived对象分配对象内存。
这是不符合operator new刚开始的设计目的的。
可以使用“内存申请错误”的调用行为改用标准的操作符::operator new,修改后的代码如下所示:
#include <stdio.h>#include <stdlib.h>#include <string>#include <iostream>class CBase{public:CBase(){}~CBase(){}void setAge(int age){m_age = age;}void* operator new(std::size_t size){<span style="color:#ff0000;">if (size != sizeof(CBase)){void *buf = ::operator new(size);printf("%s:%d:CBase:%s, buf:%p\n", __FILE__, __LINE__, __FUNCTION__, buf);return buf;}</span>if (size == 0){size = 1;}printf("%s:%d:CBase:%s, (new size, class size):(%zu, %zu)\n", __FILE__, __LINE__, __FUNCTION__, size, sizeof(CBase));void* buf = malloc(size);printf("%s:%d:CBase:%s, buf:%p\n", __FILE__, __LINE__, __FUNCTION__, buf);return buf;}void operator delete(void* buf){if (buf == NULL){return;}printf("%s:%d:CBase:%s, buf:%p\n", __FILE__, __LINE__, __FUNCTION__, buf);free(buf);return;}private:int m_age;};class CDerived : public CBase{public:CDerived(){printf("%s:%d:CDerived:%s, sizeof(class CDerived):%zu\n", __FILE__, __LINE__, __FUNCTION__, sizeof(CDerived));}~CDerived(){printf("%s:%d:CDerived:%s\n", __FILE__, __LINE__, __FUNCTION__);}void setWeight(int w){m_weight = w;}private:int m_weight;};int main(){printf("\n===============new CBase()======================\n");CBase* base = new CBase();delete base;printf("================================================\n\n");printf("***************new CDerived()**********************\n");CDerived* derived = new CDerived();delete derived;printf("***************************************************\n\n");return 0;}
测试结果如下所示:
(完)
- operator new之被Drived Class继承
- C++ new 之 placement new、operator new、new operator
- member function of a drived class(10.27)
- operator new之placement new/delete
- C++一些注意点之operator new 和new operator
- operator new之non-member operator new固守规则
- C++一些注意点之operator new 和new operator
- c++内存分配之new、operator new、placement new分析
- operator new之错误处理函数new_handler
- operator new
- operator new
- operator new
- new operator
- operator new
- operator new与new operator
- "operator new" 和"new operator "
- operator new 和new operator
- new operator与operator new
- 购物网页项目总结
- Android中的Fragment ——03(Fragment的生命周期)
- 天梯赛训练2 5-4 最长连续递增子序列 (20分)
- Linux_更改yum源
- c#switch-case
- operator new之被Drived Class继承
- 装饰者模式及其应用
- CodeForces 687C - The Values You Can Make(01背包dp)
- Java基础与案例开发详解の常用类的介绍
- JDK 1.8.0_92 Arrays.sort()方法不可用?【jdk1.8无法与myeclipse8.6匹配的问题】
- dex2oat: dex2oat
- POJ 2226 Muddy Fields(二分图匹配)
- hihocoder太阁面经算法竞赛8-Dice Possibility
- NYOJ 113 字符串替换 string类的应用