C++ 对运算符删除重写的工作方式感到困惑

C++ 对运算符删除重写的工作方式感到困惑,c++,C++,因此,我试图创建一个基类,该基类具有该类型基类的默认释放函数。根据我删除派生对象的方式,我看到了不同的行为,也许任何人都可以解释为什么在以下未调用自定义解除分配的注释情况下,我看不到覆盖工作: #include <iostream> struct B { void operator delete(void* ptr) { std::cout << "B's operator delete" << std::endl;

因此,我试图创建一个基类,该基类具有该类型基类的默认释放函数。根据我删除派生对象的方式,我看到了不同的行为,也许任何人都可以解释为什么在以下未调用自定义解除分配的注释情况下,我看不到覆盖工作:

#include <iostream>

struct B {
    void operator delete(void* ptr) { 
        std::cout << "B's operator delete" << std::endl;
        ::operator delete(ptr); 
    }
};

struct D : B {
};

template<typename T>
class E {
public:
    E(T* inst) {
        //delete inst;            // invokes the operator delete override   
        T::operator delete(inst); // invokes the operator delete override
        //operator delete(inst);  // does not invoke the operator delete override
    }
};

int main() {
    D* dp = new D();
    E<D>* ep = new E<D>(dp);
    delete ep;
}
#包括
结构B{
void运算符删除(void*ptr){

STD::CUT< P>不完全肯定这一点,但我认为这是Stephen Dewhurst在C++ GoCHCHAS 23中调用“操作符函数查找异常”的一个场景。他调用显式窗体来调用操作符重载“函数调用语法”,并显示一个例子,在该示例中,中缀语法和函数调用语法在名称查找方面有所不同。 函数调用语法的使用遵循搜索函数名的标准查找顺序。对于成员函数
X::f
,编译器将首先在类
X
中查找名为
operator%
的函数。一旦找到名称,它将不会继续在外部范围中查找添加项所有名为
运算符%
的函数

让我们将此应用于
操作符删除
场景

template<typename T>
class E {
  public:
    E(T* inst) {
        // delete inst; // Ok, infix call syntax
        // T::operator delete(inst); // Ok, qualified lookup enforced
        operator delete(inst); // The "anomaly"! This finds the operator delete for E
    }
};
模板
E类{
公众:
E(T*仪表){
//delete inst;//确定,中缀调用语法
//运算符delete(inst);//好,强制执行限定查找
运算符delete(inst);//该“异常”!它为E查找运算符delete
}
};
在这里,名称查找在
E
提供的
operator delete
处停止,这是默认的全局实现。您可以通过将
operator delete
成员函数添加到
E
解除分配函数(
operator delete
)来验证这一点for类是该类的静态成员函数。
delete
表达式具有特殊属性,即查找释放函数时也会考虑特定于类的释放函数[expr.delete]/9,这就是为什么

delete inst;
确实会调用正确的释放函数。当您只是手动写入

operator delete(inst);

这实际上是对函数族的调用,称为“代码>运算符删除<代码>。这样的调用将只经过正常的过载解决方案,除非明确地给出一个合格的ID,否则它将不考虑静态成员函数,这是

T::operator delete(inst);

你确定你不只是想要一个虚拟析构函数吗?我选择了一个错误的dupe,我找不到另一个合适的dupe,但是给函数命名
operator delete
是件麻烦事。你永远不应该调用
operator delete(objectptr)
。仅
删除objectptr
。您可以调用
somescope::operator delete(voidptr)
在另一个
操作符delete
函数中。这只是一个最小的示例代码,我希望能够调用deallocator,而无需对给定的typename运行析构函数。你说@StoryTeller是什么意思?这甚至是最小的,有着同样的问题。感谢你的详细解释!我当时的印象是在调用
运算符时删除(inst)
将与
delete inst
相同,只是不执行析构函数。是否有可能在不使用前缀T的情况下获得相同的行为::?可以使用中缀调用语法
delete inst;
,这是不带前缀的。但是如果您想要详细的函数调用语法-不,它不是谢谢你的解释,我认为delete和operator delete除了一个执行析构函数,另一个执行析构函数外,都会以相同的方式运行not@PhilipM在表达式中使用运算符与调用运算符函数是一样的,这是一个常见的误解。运算符函数只是一个具有编译器在计算某些类型的表达式时将调用的特殊名称,以实现该类型表达式行为的某些部分。
new
delete
表达式就是很好的例子。新表达式的作用远不止调用
操作符new
。它创建了一个动作ual对象,可能涉及调用构造函数,处理分配函数的潜在故障…
T::operator delete(inst);