如何防止一个对象通过指向其父类型的指针被删除?

问题描述 投票:0回答:1
struct A
{};

struct B : A
{
    operator A() const = delete; // not work
};

int main()
{
    B* p_derived = new B();
    delete p_derived; // ok

    // How to make the following two lines illegal?
    A* p_base = new B();
    delete p_base; 
}

A父类型的定义不能被改变,它的析构器也不能被删除。virtual;所以 B的对象不应该被一个指向 A.

我不能用 struct B : protected A {};因为我想 B 继承所有 public 成员 A 纹丝不动 public.

C++的混搭模式这是个常见的问题。

除非mixin类通过指向原类的指针被多态删除,否则是可以的。

我的问题是:如何防止一个对象通过指向其父类的指针被删除?

如何防止一个对象通过指向其父类的指针被删除?

c++ oop design-patterns polymorphism virtual-destructor
1个回答
1
投票

把A的destructor做成protected,那么子类就可以访问它来正确地毁灭B类型的对象,但是其他地方就不能访问了。

struct A
{
protected:
   ~A() {}
};

struct B :  A
{
};

int main()
{
    A* p_base = new B();
    delete p_base; // This is now an error
}

如果你真的不能改变A,那么你可以这样做。

struct A
{
};

struct AA : A
{
protected:
   ~AA() {}
};

struct B :  AA
{
};

int main()
{
    AA* p_base = new B();
    delete p_base; // How to make this a compile-time error?
}

但如果你通过A而不是AA来删除的话,这是不可行的。

根据你的问题的性质,你可以使用'#define A AA'或者其他类似的丑陋的黑客方法来使其在现有的代码库中工作。

struct A
{
};

struct AA : A
{
protected:
   ~AA() {}
};

#define A AA
struct B :  A
{
};

int main()
{
    A* p_base = new B();
    delete p_base; // How to make this a compile-time error?
}

1
投票

简而言之,你不能这样做。

考虑一下这样的函数

// definition of struct A

void func(A *p)
{
    delete p;
}

和另一个编译单元的调用者

// definitions of struct A and B as in question

void func(A *);

void caller()
{
     func(new B);
}

在这种情况下,在 func() 的类型完全不可见。B更不用说指针的潜力了。p 其获得的实际积分为 B. 由于 func() 是否 delete p,函数 caller() 引起 func() 有未定义的行为。

在这种情况下,真正的解决方法是 B 不应继承 A. 这一点已经有了强烈的暗示。A 没有 virtual 的destructor。 这将防止 caller() 呼叫 func() 带着 B *.

如果你想 B 以提供与 A的所有成员函数。B 所以他们转发到一个包含 A. 例如:

 struct B
 {
      B() : a() {};    

      void some_member(some_type arg)
      {
          a.some_member(arg);      // assume A has this member that accepts these arguments
      }

      private:

         A a;
 };

很明显,有一些选项可供选择,如果 struct A 可以修改,但问题明确指出了不可能修改的用例。

© www.soinside.com 2019 - 2024. All rights reserved.