当前位置:  开发笔记 > 编程语言 > 正文

如何覆盖C++中的删除行为?

如何解决《如何覆盖C++中的删除行为?》经验,为你挑选了2个好方法。

我遇到的问题是,据我所知,删除操作符应该是一个静态函数,但有时编译器(VC++)似乎将它视为动态.

鉴于:

class Base
{
public:
  void* operator new(size_t size) { /* allocate from custom heap */ }
  void operator delete(void *p) { customFree(p, sizeof(Base)); }

  Base() {}
  virtual ~Base() {}
};

class Derived: public Base
{
public:
  void* operator new(size_t size) { /* allocate from custom heap */ }
  void operator delete(void *p) { customFree(p, sizeof(Derived)); }

  Derived() {}
  virtual ~Derived() {}
}

我看到的是删除基指针将导致调用Derived::opeator删除.

Base *p = new Derived();
delete p; //calls Derived::operator delete

如果我没有定义任何析构函数,那么我得到了我预期的结果:调用Base :: operator delete.这似乎正在发生,因为编译器在定义析构函数时将一个名为"标量删除析构函数"的函数插入到vtable中.然后该函数将调用.Derived::delete

所以我有问题:1)这是标准行为吗?2)我什么时候应该使用

void operator delete( void *, size_t );

void operator delete( void * );

如果以上是标准行为?



1> Johannes Sch..:

这肯定是标准行为.如果使用派生类的operator new,也将使用它的 operator delete(也请注意,即使你没有明确地告诉编译器那些函数是静态的,它们也是隐式声明的).可能存在一个顽皮的情况,即派生类中有一个operator new,但相应的operator delete在基类中.我认为这是有效的,但我会避免这种情况.依赖于基本运算符删除,同时在派生类中定义自己的运算符new将不可避免地造成麻烦.

如果我没有定义任何析构函数,那么我得到了我期望发生的事情:

你将得到未定义的行为:)一切都会发生,包括你期望的(错误的).通过指向另一种类型的对象的基指针进行删除需要虚拟析构函数.隐式声明的析构函数不是虚拟的.

我什么时候应该使用void operator delete(void*,size_t);

如果您希望在运算符delete中分配已知的大小.我写了这里的含义: C++ new运算符除了分配和ctor调用之外还做了什么?.如果你使用(来自你的重载成员操作符delete/new)全局操作符new&delete来获取你的内存并释放它,甚至是malloc/free,你不需要那些大小信息.但它可能对记录目的很有用.



2> 小智..:

(嘿,我应该先发帖然后再查看:))

以下是标准的相关摘录:

1 delete-expression运算符销毁 由new-expression创建的派生程度最高的对象 (intro.object)或数组.delete-expression ::: opt delete cast-expression :: opt delete [] cast-expression第一种方法是非数组对象,第二种方法是数组.操作数应具有指针类型,或具有指针类型的单个转换函数(class.conv.fct)的类类型.结果类型为void.

3在第一个备选(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为为未定义. 在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为是未定义的.19)

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有