当基类在析构时需要知道派生类的信息时,如何避免在析构函数中调用虚函数?

问题描述 投票:0回答:1

目前我遇到以下情况:

我有一个基类

Base
,有一个
void* V
成员,实际上可能是
A*, B*, C*
,并且三个(只有三个,固定数量)类类别将从
Base
派生,每个类别都会填充
V
不同类型的数据。我不希望用户在每个派生类的析构函数中手动释放
V
,然后
Base
必须确定
V
的真实类型并调用它的析构函数。但由于虚函数被视为非虚函数,那么如何获得
V
的类型呢?如果我另外添加一个
_type
变量,它将占用更多内存(并且它将强制用户为每个构造函数填充
_type

示例如下:

class Base {
public:
   void* V;
   virtual ~Base() { /* how to free V? */ }
};

class A : public Base {
public:
   A() : V((void*) new int) {}
   virtual ~A() { /* I don't want to let user 
                     write delete (int*) V in every destructor of 
                     class of type 1, since the user may forget. */
   virtual int type() const { return 1; }
};

class B : public Base {
public:
   B() : V((void*) new double) {}
   
   virtual int type() const { return 2; }
};

class C : public Base {
public:
   C() : V((void*) new int[4]) {}
   
   virtual int type() const { return 3; }
};


我的主要目的是为用户做更多的事情,而不是让他们手动管理内存,那么对于这种情况,有没有更好的方法来达到同样的目标?或者是否有解决方法可以正确释放

V

c++ polymorphism destructor virtual-functions
1个回答
2
投票

如果我理解正确的话,你有一个实体层次结构,其中派生实体(

A
B
等)每个都持有不同的数据类型。

最简单的解决方案是从

V
中删除
Base
并向每个派生类添加特定的数据成员(不带指针)。这样您就根本不必处理删除
V
的问题。

如果出于某种原因您想要将主要实体与它们所持有的数据分开(基础可以访问它),您可以创建一个单独的数据实体层次结构(

BaseData
AData
BData
等) .)。您还可以使用智能指针来避免手动内存管理。

这如下所示:

#include <memory>
#include <array>

// Hirarchy of data entities:

struct BaseData { 
    virtual ~BaseData() = default; // required for proper destruction of derived classes
};

struct AData : public BaseData {
    int m_data{ 0 };
};

struct BData : public BaseData {
    double m_data{ 0 };
};

struct CData : public BaseData {
    std::array<int, 4> m_data{ 0 };
};


// Hirarchy of main entities:

class Base {
public:
    std::unique_ptr<BaseData> m_V;
    virtual ~Base() = default; // required for proper destruction of derived classes
};

class A : public Base {
public:
    A() { m_V = std::make_unique<AData>(); }
};

class B : public Base {
public:
    B() { m_V = std::make_unique<BData>(); }
};

class C : public Base {
public:
    C() { m_V = std::make_unique<CData>(); }
};

备注:

  1. 我使用
    std::array
    而不是原始 C 数组。
  2. 数据实体
    structs
    只是为了简单起见。
© www.soinside.com 2019 - 2024. All rights reserved.