cppyy模板class实例化没有虚析构函数

cppyy template class instantiation has no virtual destructor

我在 Python 代码中设置了以下 child class:

class NodeRewriter(SyntaxRewriter[SyntaxNode]):
   
   def visit(self, node: SyntaxNode):
      print(node)

这里是相关的objects:

RuntimeWarning: class "slang::SyntaxRewriter<slang::SyntaxNode>" has no virtual destructor
  class NodeRewriter(SyntaxRewriter[SyntaxNode]):
>>> print(SyntaxRewriter)
<cppyy.Template 'slang::SyntaxRewriter' object at 0x7fb76c0c15b0>
>>> print(SyntaxNode)
<class cppyy.gbl.slang.SyntaxNode at 0x55e4302f07c0>
>>> print(SyntaxRewriter[SyntaxNode])
<class cppyy.gbl.slang.SyntaxRewriter<slang::SyntaxNode> at 0x55e4308df4b0>
>>> 

我所做的只是创建 class,我还没有从中创建任何 objects。我在导入包含 class 和其余 cppyy 代码的文件时收到警告。

我需要自己添加一个__destruct__()方法吗?似乎警告不是指我的 child class,而是指它继承自的模板实例化。

没看过 SyntaxRewriter 的来源 ...

如果 C++ 中的 class 没有虚析构函数,它通常不适合作为基 class,因为如果 delete 在基 [=32= 上调用] 指针,只调用基类的析构函数,而不是指针底层的实际派生 class 之一。有时没关系,有时会出现资源泄漏,有时会出现虚假崩溃。

如果全部用 C++ 完成,那么当您执行此操作时它会更明确,只要您永远不会 delete 这样的基 class 指针就可以了。代码是明确的,你可以注意永远不要这样做。但是在交叉派生中,在 C++ 基础 class 和 Python 派生的 class 之间有一个存根可能并不明显,两者都用于调解调用和管理内存。因此,该存根和实际删除都被隐藏了。此外,交叉派生最常见的用例是将派生的 Python class 的实例发送到 C++ 领域,在那里它们可能会被管理。然后,如果 C++ 在某个时候清理对象,没有 C++ 基的虚拟析构函数,存根的析构函数将不会被调用,并且 Python 部分会泄漏(它会有一个引用计数太多永远不会被清除)。只是警告b/c如果Python管理对象,即使没有virtual destructor也不会泄漏

实施 __destruct__ 不会有什么不同(并且在任何情况下都不应该这样做;如果需要资源清理,请改用 __del__),因为问题(如果有的话)是之前编译的C++造成的,事后无法更改。

(请注意,可以抑制 Python 警告,请参阅 https://docs.python.org/3/library/warnings.html。)