Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何防止通过指向其父类型的指针删除对象?_C++_Oop_Design Patterns_Polymorphism_Virtual Destructor - Fatal编程技术网

C++ 如何防止通过指向其父类型的指针删除对象?

C++ 如何防止通过指向其父类型的指针删除对象?,c++,oop,design-patterns,polymorphism,virtual-destructor,C++,Oop,Design Patterns,Polymorphism,Virtual Destructor,A的定义不能更改,其析构函数不是虚拟的;所以B的对象不应该被指向a的指针删除 我不能使用structb:protecteda{},因为我希望B继承A的所有public成员,并使其保持不变public 在中,这是一个常见的问题: 这是可以的,除非通过指向原始类的指针以多态方式删除mixin类 我的问题: 如何防止通过指向其父类型的指针删除对象?使a的析构函数受保护,则子类可以正确地访问B类型的破坏对象,但其他地方无法访问该对象 struct A {}; struct B : A { op

A
的定义不能更改,其析构函数不是
虚拟的
;所以
B
的对象不应该被指向
a
的指针删除

我不能使用
structb:protecteda{}
,因为我希望
B
继承
A
的所有
public
成员,并使其保持不变
public

在中,这是一个常见的问题:

这是可以的,除非通过指向原始类的指针以多态方式删除mixin类

我的问题:


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

使a的析构函数受保护,则子类可以正确地访问B类型的破坏对象,但其他地方无法访问该对象

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; 
}
如果您真的无法更改,那么您可以这样做:

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

struct B :  A
{
};

int main()
{
    A* p_base = new B();
    delete p_base; // This is now an error
}
但是,如果通过A而不是AA删除,则此操作不起作用

根据问题的性质,您可以使用“定义AA”或其他类似的丑恶手段来使用现有的代码库

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?
}

简而言之,你不能

考虑这样一个函数

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?
}
以及另一个编译单元中的调用者

// definition of struct A

void func(A *p)
{
    delete p;
}
在这种情况下,
func()
中的代码在所有类型的
B
中都不可见,更不用说它接收的指针
p
实际指向a
B
的可能性了。由于
func()

在这种情况下,真正的解决方案是
B
不应从
A
继承。事实上,
a
没有
virtual
析构函数,这已经强烈暗示了这一点。这将阻止
caller()
使用
B*
调用
func()

如果希望
B
提供与
A
相同的接口,则需要使用组合,并定义
B
的所有成员函数,以便它们转发到包含的
A
。比如,

// definitions of struct A and B as in question

void func(A *);

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

显然,如果
结构A
可以修改,则有一些选项可用,但问题明确说明了不可能修改的用例。

您打算如何删除B的实例?如果您不能更改
A
,则无法实现这一点。我会重新考虑这个问题。也许
B
应该“has-a”
a
而不是“is-a”
a
,并且删除了typecast操作符和一组引用a字段的字段。在C++的混合模式中,这是一个常见问题@user207421不,这实际上不是mixin模式的常见问题,因为mixin和多态删除在实践中很少同时出现。如果需要这样的东西,那么base/mixin可以是多态的,包括给它一个虚拟析构函数。一般来说,mixin类不打算以多态方式使用,因此它们没有虚拟析构函数,不应该以多态方式删除。如果将
p\u base
传递给一个函数,该函数接受实际的
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;
 };