【问题标题】:Invoke a templated member from a c-function using void pointer使用 void 指针从 c 函数调用模板化成员
【发布时间】:2018-08-01 19:26:08
【问题描述】:

我的 c++ 代码必须与底层 c 库一起使用。我有一个看起来像这样的 c++ 对象:

template <typename T>
class MyClass
{
public:
  explicit MyClass(int x)
  : mVar(x)
  {
  }

private:
  int mVar;
};

稍后在我的 c++ 代码中,我执行以下操作:

  auto p = new MyClass<int>(10);

  call_c_lib_function((void*) p);

c 函数将指针“p”保存在更大的 c 结构中。后来当大 c 对象被销毁,它调用删除处理程序。

void
c_delete_handler(void* data)
{
  // data is holding the pointer value 'p' from above.
}

由于对象被销毁,我需要释放分配的对象。 根据 c++ 规范,'delete void_ptr' 是未定义的,因为它不知道如何 调用适当的析构函数。如何在适当的情况下调用删除 模板对象?

我能想到的一个解决方案是围绕 MyClass 指针创建一个包装结构。

struct Wrapper {
  enum template_type {
    template_int,
    template_double,
    template_string,
    ...
  };

  int template_type;
  void* obj_ptr;
};

在调用 call_c_lib_function 之前,我会执行以下操作:

  auto p = new MyClass<int>(10);
  auto w = new Wrapper()
  w.template_type = Wrapper::template_int;
  w.obj_ptr = (void*) p;

  call_c_lib_function((void) w);

现在在删除处理程序中,我可以执行以下操作:

void
c_delete_handler(void* data)
{
  Wrapper* w = (Wrapper*) data;

  switch (w->template_type) {
    case Wrapper::template_int:
      delete (MyClass<int>*) w->obj_ptr;
      break;

    case Wrapper::template_double:
      delete (MyClass<double>*) w->obj_ptr;
      break;
    ...
  }
}

这是正确的方法吗?有更好的选择吗? 将不胜感激任何投入。谢谢。

【问题讨论】:

  • 这更像是一个 C++ 问题而不是 C 问题。标签已编辑。
  • 只需用智能指针(shared_ptrunique_ptr 等)分配它,然后让它自己收集。 void* 在 C++ 中的使用并不多。否则,您必须跟踪指针的类型并在删除之前对其进行强制转换。

标签: c++ c templates void-pointers


【解决方案1】:

如果可以的话,不要使用Wrapper,而是使用基类。

class MyBase
{
   public:
      virtual ~MyBase() {};
};

template <typename T>
class MyClass : public MyBase
{
   public:
     explicit MyClass(int x) : mVar(x) {}

   private:
     int mVar;
};

然后

void c_delete_handler(void* data)
{
  Base* basePtr = reinterpret_cast<Base*>(data);
  delete basePtr;
}

这种方法无需跟踪MyClass 是否使用intdoublestd::string 或...进行实例化。

【讨论】:

  • 这会为派生类型调用正确的析构函数吗? (不是说不会 - 老实说,我不确定。)
  • @3Dave,是的,它会的。这就是 virtual 析构函数的用途。
  • 这正是我想要的。谢谢。
猜你喜欢
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多