【问题标题】:Overriding operator覆盖运算符
【发布时间】:2010-11-16 06:24:57
【问题描述】:

关于构造函数重写的任何人..

我有这个

void  operator delete(void*) {}

void  operator delete(void* p, void*) {}

在我的类中..看起来像重载(相同的函数名和返回类型,但参数列表不同),但它的覆盖......它是如何覆盖的......

谁能解释一下这两行的功能。

【问题讨论】:

  • 你能用删除表达式调用第二个重载吗?
  • 它没有超载.. 它的压倒一切.. 不,实际上我不了解这两个功能
  • 一个问题:为什么?详细说明;你想达到什么目的?如果你想在你的类被释放时有特殊的行为,那就写一个析构函数吧。
  • 您永远无法覆盖operator delete,因为operator delete 始终是static,无论是否明确声明。覆盖仅适用于 virtual 函数。
  • @Charles: operator delete 是一种类似 :-) 的一般规则的例外。对于多态静态已知类,它在最派生(动态)类中查找。但我忘记了细节;如果我需要做这些事情,我会查一下。干杯,

标签: c++ overriding overloading new-operator


【解决方案1】:
void  operator delete(void*) {}
void  operator delete(void* p, void*) {}

这些是自定义释放函数。释放函数通过deleteexpression 调用。例如

YourClass* p = new YourClass();    // Allocates memory & calls constructor
// ... whatever, then
delete p;                          // Calls destructor & deallocates memory

对于您的类,上面最后一行中的 delete 表达式将首先调用析构函数,然后它会调用该类定义的单个 void* 参数释放函数,即您的两个函数中的第一个,如果该释放是可访问的。

但是,释放函数可能被声明为privateprotected,目的是使其不可访问。在第一种情况下,类自身代码之外的delete 表达式将无法编译(无法访问的释放函数)。如果是这样,那么这可能就是重点——或者,如果根本没有意义,请不要感到惊讶。

顺便看看this tutorial。这显然是网络上对 C++ 的最不坏的免费介绍。 Bruce Eckel 的电子书"Thinking in C++" 也是免费的,但它有一些错误和错误信息(不过以前正好相反,曾经 cplusplus.com 上的教程非常糟糕)。

干杯,

【讨论】:

  • +1 Thinking in C++ 是一本好书,尤其是。对于任何一开始就对编程有所了解的人。如果您知道书中的一些错误,我敢打赌,如果您为他指出这些错误,埃克尔会很高兴的。
  • @daramarak 我提到了关于错误,因为优秀的 Bruce 没有修复报告的错误,所以这些年来人们一次又一次地问同样的问题。干杯,
【解决方案2】:

他们重载了 delete 操作符,第二个是使用“placement delete”。放置 new/delete 是一种技巧,因此您可以让 C++ 构造函数在您提供的内存之上(而不是 ::new)初始化类,并且可能使用您在此处看到的其他参数。 Google 可以为您填写血淋淋的详细信息。

【讨论】:

  • 这是 C++ 的一个令人讨厌的角落。通常当您调用 new 和 delete 时,您将使用 C++ 编译器的实现来实际分配和释放内存。不过,C++ 允许您覆盖此行为,并且您可以声明自己的 new 和 delete 版本。如果你(或其他作者)这样做,你可以做各种疯狂的(有时是有用的)事情,你可以在调用 new 和 delete 时添加额外的参数。这个话题比我现在能深入一点,但是谷歌上的“placement new”和“placement delete”,你会发现很多信息。
  • 在我看来,我真的不会将它们描述为“黑客”。它们是可以像任何其他运算符一样重载和自定义的运算符。这算不算“黑客”?
  • @Moo-Juice,我曾经是一名自豪的 C++ 语言律师,曾经我可能会同意你的观点,认为这是一种有用的功能,但我看到了优秀程序员的烂摊子从这种东西中制造出来,我现在只是认为这是一个在某些情况下可能有用但通常应该避免的klugy hack。在您花费大量时间与其他偶然发现此类事情的程序员合作,并在清理他们造成的混乱时陷入困境之后,您可能会同意。
【解决方案3】:

这些是运算符删除重载,在对象上调用delete 时调用。从 3.7.3.2(释放函数)开始:

每个释放函数都应返回 void,其第一个参数应为 void*。释放函数 可以有多个参数。 如果一个类 T 有一个名为 operator 的成员释放函数 只使用一个参数删除,则该函数是一个通常的(非放置)释放函数。如果 类 T 没有声明这样的操作符 delete 但确实声明了一个成员释放函数 命名运算符 delete 正好有两个参数,第二个参数的类型为 std::size_t (18.1),那么这个函数就是一个普通的释放函数。

在 12.5 免费商店中:

当删除表达式被执行时,选择的释放函数应该被调用,地址为 要回收的存储块作为其第一个参数和(如果使用双参数样式)的大小 块作为它的第二个参数

我不确定您的第二个函数是否可以被调用,因为它不是“通常的释放函数”。

【讨论】:

  • 可以手动调用,也可以通过new表达式调用相应的placement new,如果构造函数抛出。这是自动调用展示位置删除的唯一情况。微软曾经打出“聪明”的想法,使用placement new 来帮助调试,但是忘记定义对应的placement delete。结果导致内存泄漏,但仅在调试版本中... :-) 这是最臭名昭著的 MFC 错误之一。干杯,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-05
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-02
相关资源
最近更新 更多