新建/删除运算符重载和基类

时间:2014-08-04 14:41:05

标签: c++ oop operator-overloading new-operator delete-operator

目前我非常头疼。

基本上我有这个:

Class A -> Class B
Class A -> Class C
Class A -> Class D

Class E with constructor with declaration E(int, A *objptr, bool IsObjPtrOwner = true)

如您所见,B C和D继承自A,A是基类。 D类必须具有特定的对齐方式(因为SSE2在其中使用),因此我在其中重载了new / delete,每次动态地对象提供对齐的内存块。我也应该提一下,因为A B C和D不同,我几乎猜测B C A和D根本没有相同的大小。

所以我希望能够做到这一点:

E eobj(12, new D(2.001), true);

因为参数IsObjPtrOwner是真的,所以我编写了我的类E,这样,如果成员m_IsObjPtrOwner为真,则在E的析构函数中删除指针m_objptr。

这对我来说非常方便,能够在构造对象E时直接动态分配A的派生类之一,而不必在以后关心它。这样做的原因是我将在整个程序中制作很多E类实例,每次使用不同的B / C / D实例。因此,我希望不必每次构建E实例时都保留每个指针的副本。

所以我尝试将new / delete运算符设为纯虚拟,但它只是不起作用。该死的功能必须是静态的,非常麻烦。所以我试图尽可能地绕过这个,但我最终发现我不能使用"这个"内部静态函数。

我该怎么办?我怎么才能实现这个梦想?我有一个梦想......


编辑:出于某些原因,人们完全不了解我想说的话。

我有一个基类A和一组来自A的派生类B / C / D.我有一个E类,在它的构造函数中作为一个参数,一个A类的指针,然后存储在一个成员中,比如说m_bcdobj,所以我有这个:

class B : public A {
    B(double x) : m_x(x) { bla bla bla}
    void *operator new(size_t size)   { return Util_MemAlign(size, 4); }
    void  operator delete(void* ptr)  { Util_AlignFree(ptr); }
}
class C : public A {
    C(double x) : m_x(x) { bla bla bla}
    void *operator new(size_t size)   { return malloc(size); }
    void  operator delete(void* ptr)  { free(ptr); }
}
class D : public A {
    D(double x) : m_x(x) { bla bla bla}
    void *operator new(size_t size)   { return Util_MemAlign(size, 16); }
    void  operator delete(void* ptr)  { Util_AlignFree(ptr); }
}

如您所见,每个人都有不同的对齐要求。

现在我有一个E级课程:

class E {
    public:
        E(int z, A *bcdobj, bool IsObjPtrOwner = true) : m_z(z), m_bcdobj(bcdobj), m_freebcd(IsObjPtrOwner) { bla bla bla }

        ~E() { if (m_freebcd) { delete m_bcdobj; } }

    private:
        A *m_bcdobj;
        int m_z;
        bool m_freebcd;
}

所以我希望能够做到这一点:

E einst(2, new D(2.001));

即。我没有保留分配的D对象的副本。分配的D对象将被释放,而#34; einst"被毁了。问题是这段代码不起作用。在~E()中删除m_bcdobj时,不会调用D中的重载删除操作符。

谢谢!

1 个答案:

答案 0 :(得分:4)

operator delete的特殊之处在于,尽管它是一个静态成员,但如果该类具有虚拟析构函数,则会动态调度它。 §12.5[class.free] / p4:

  

如果delete-expression用于释放其对象的类对象   static类型有一个虚拟析构函数,deallocation函数是   在动态类型的虚拟定义点选择一个   析构函数(12.4)。

例如,

struct B {
    virtual ~B() = default;
    void operator delete(void* ptr) { 
        std::cout << "B's operator delete" << std::endl; ::operator delete(ptr); 
    }
};
struct D : B {
    void operator delete(void* ptr) { 
        std::cout << "D's operator delete" << std::endl; ::operator delete(ptr); 
    }
};
int main() {
    B* bp = new D;
    delete bp; //1: uses D::operator delete(void*)
}

prints

D's operator delete

因此,给A一个虚拟析构函数,你应该看到正确的operator delete调用:)。