C++ 非多态派生类的基类

C++ 非多态派生类的基类,c++,C++,我有以下类定义: class BaseHandle { /* Lots of things */ }; class VertexHandle : public BaseHandle { /* Only static members and non-virtual functions, default dtor */ }; class EdgeHandle : public BaseHandle { /* Dito */ }; class FaceHandle : public BaseH

我有以下类定义:

class BaseHandle { /* Lots of things */ };
class VertexHandle : public BaseHandle {
    /* Only static members and non-virtual functions, default dtor */ };
class EdgeHandle : public BaseHandle { /* Dito */ };
class FaceHandle : public BaseHandle { /* Dito */ };
所有类都没有虚拟函数或基。
派生类仅派生自
BaseHandle
,不添加任何非静态成员,也不添加非默认DTOR

我想将
顶点-
边-
面句柄
保存在同一个向量中:

std::vector<BaseHandle*> handles;
std::向量句柄;
但是它不起作用,如果我检索
BaseHandle
对象并想
dynamic\u cast
将它们转换为派生对象,它会失败,因为类不是多态的(这是我的解释,也许我错了)


如何实现
BaseHandles
的公共向量?我应该提到的是,我不能更改类定义,因为它们是第三方库的一部分。

您的父类中需要有一个虚拟析构函数,才能以多态方式使用它

class BaseHandle 
{
  public:
    virtual ~BaseHandle();

  ...

};
这是因为
dynamic\u cast
与RTTI(运行时类型信息)一起工作,只有当您的类至少有一个虚拟成员函数时,RTTI(运行时类型信息)才可用

这也将防止资源泄漏,否则只会破坏实例的父类部分


变通办法 您可以使用的
std::vector
,不仅可以通过不必手动调用
new
delete
来避免内存泄漏,而且该智能指针还具有神奇的特性(它存储删除器以根据其构造方式调用销毁),可以解决您的问题:

int main()
{
  std::vector<std::shared_ptr<BaseHandle>>      shared_vec;

  shared_vec.push_back(std::make_shared<VertexHandle>());

} // At the end of scope all destructors are called correctly
intmain()
{
std::向量共享向量;
共享向量推回(std::make_shared());
}//在作用域的末尾,所有析构函数都被正确调用
如果您没有访问c++11的权限,可以使用

struct thing
{
    enum Type { vertex, edge, face };
    Type type;
    union
    {
        VertexHandle * vh;
        EdgeHandle * eh;
        FaceHandle * fh;
    };
};

但基本上是一团糟。。。你确定要这样做吗?看起来您正在一个数组中存储多个类型,尽管事实上没有办法多态地使用它们,那么实际上只有一个数组而不是三个数组是不是有一个很好的理由呢?

如果所有派生自
BaseHandle
的类都只使用来自
BaseHandle
的单一继承(加上可能是从带有普通dtor的空类继承,这些类需要进行空基类优化),并且除了非
虚拟
函数和
静态
成员之外,不要添加任何东西,并且所有派生类都使用默认dtor或等效的dtor,您可以将
静态
强制转换到目标


但是请注意,无法知道哪些派生类(如果有的话)实际上是派生类。

下面是Kerrek的评论。您可以“创建自己的并行类层次结构,并将这些类型中的每一个添加为成员”。例如:

class MyBaseHandle {
 public:
  virtual ~MyBaseHandle(){}
  virtual Box getBoundingBox() const = 0;
};

class MyEdgeHandle : public MyBaseHandle {
  std::unique_ptr<EdgeHandle> handle_;
 public:
  MyHandle(std::unique_ptr<EdgeHandle> handle) : handle_(std::move(handle)) {}
  Box getBoundingBox() const override;
};

要使多态类发挥作用,您至少需要一个虚拟函数:析构函数。您可以创建自己的并行类层次结构,并将这些类型中的每一个添加为成员。问题有解决方案。使用虚拟函数。
typeid
static\u cast
的组合属于问题域您正在重新创建旧的
类BaseHandle{int TYPE;…};开关(TYPE){…
习惯用法,众所周知这是一个巨大的混乱。是否有任何派生类都有额外的成员,分别比
BaseHandle
更多的基类?它们是否有用户定义的DTR?如果在使用它之前必须
动态\u cast
一些东西,这通常是一个糟糕设计的标志。我怀疑这些对象是否是t属于同一个
向量
。我应该提到的是,我不能更改类定义,因为它们是第三方库的一部分。@Terenchill那么这些类不是为与多态性一起使用而设计的:)只有黑客和变通办法才能解决问题works@TerenceChill我已经添加了一个不太可怕的变通方法任何虚拟函数或基都足以多态性地使用它,虚拟dtor只是多态性地删除它所必需的。虽然如果一个人有任何虚拟成员或基,那么将dtor虚拟化也只是常识…我认为这个基类必须是多态的。你确定它足以使派生类多态吗?我想把所有句柄放在一个空间数据结构中。这样我可以问,哪些顶点、边和面在一个边界框内。数据结构的查询结果是
BaseHandles
。通过铸造
BaseHandle
我就知道我f它是一个顶点、边或面。一个解决方案是有三个空间数据结构,但这很难看。很公平。不幸的是,如果没有多态性,你在这里做的每件事都会很难看,我认为三个单独的数组可能是最不难看的。如果我不知道是哪一个,我怎么能
静态地
a
基句柄
BaseHandle
指向的派生类?没有虚拟函数就意味着没有rtti,所以我不能使用
typeid
然后强制转换,对吗?对。你只需要从
BaseHandle
的成员那里了解带外知识或其他任何东西。如果这很重要,它可能不重要。
Box MyEdgeHandle::getBoundingBox() const {

  // Get data from EdgeHandle
  auto v1 = handle_->getVertex1();
  auto v2 = handle_->getVertex2();

  // create box from edge data...

  return box;
}