TInterfacedObject 自动内存管理是否也适用于 C++Builder?

Does TInterfacedObject automatic memory management also work with C++Builder?

博客文章“Application Development with C++Builder and Delphi”说

Almost anything you write in Delphi can easily be used in C++Builder (...) You can write an object once for a Delphi project, and then reuse it, unchanged, in a C++ project.

关于 TInterfacedObject 及其基于引用计数的自动内存管理,这是否也适用于 C++Builder 而不会造成内存泄漏?还是基于 C++ 的内存管理与这种基于引用计数接口的技术不兼容?

Delphi / C++ documentation for TInterfacedObject 说(由我突出显示):

TInterfacedObject provides basic reference-counting functionality that makes its descendent classes useful in both Delphi and C++ code.

请注意:这个问题是关于在 C++Builder 项目中直接编译 Delphi / Object Pascal 源代码(afaik 在完成 C++Builder 预编译器 运行 之后),而不是通过动态链接 (DLL)

C++ 编译器不会发出代码来调用 AddRefRelease。 C++ 中没有特殊的 interface 类型。相反,您需要确保对 AddRefRelease 进行了必要的调用。这通常是通过将原始接口包装在智能指针中来实现的。在 C++-Builder 中,您可以选择使用 DelphiInterface<T>TComInterface<T>.

Serg 在这篇文章中谈到了这个话题:Consuming Delphi interfaces in Dephi and C++。那篇文章的总结值得重复:

Some details worth being mentioned:

  • Delphi interfaces are always derived from IUnknown; a corresponding pure abstract C++ class should also define IUnknown methods;
  • Delphi interface type is kind of a pointer to the corresponding C++ abstract class, so sometimes we need one more level of indirection in C++ code;
  • Delphi interface variables are always initialized to nil by the compiler; in C++ we need default constructor to implement the nil-initialization;
  • Delphi interfaces are automatically released (i.e. call IUnknown._Release method) when an interface variable goes out of scope; In C++ we implement the same functionality in destructor;
  • Interface assignment in Delphi implicitly calls _Addref and _Release methods of IUnknown; in C++ we overload the assignment operator to implement the interface assignment correctly;

C++ 编译器不会像 Delphi 那样直接在 __interface 上实现引用计数。但是,System 中有一个方便的模板,用于包装接口和提供引用计数,System::DelphiInterface, and this is the standard C++ Builder way 编写行为类似于 Delphi 的代码。

在使用接口编译 .pas 文件时,使用它的类型会在 .hpp 文件中自动生成,也可以在您的 C++ 代码中轻松创建。事实上你可能以前见过它们——使用这个模板自动生成的类型名称都以 _di_ 开头,例如 Delphi 接口 IMyInterface 的转换是 _di_IMyInterface.

直接从帮助文件中复制link就是这个例子:

// Interface that exposes an Add(..) method
 __interface  INTERFACE_UUID("{D0C74612-9E4D-459A-9304-FACE27E3577D}") IAdder  : public    System::IInterface 
 {
    virtual int __fastcall Add(int I, int J) = 0 ;
 };
 typedef System::DelphiInterface<IAdder> _di_IAdder;

在你的 C++ 代码中到处使用 _di_Adder 而不是 IAdder,你会发现你的引用被计算在内。

有用的读物​​是 entire section on DAX,C++ Builder 中新的(从 XE 开始)标准 COM 系统,它取代了 ATL。可以在早期版本的 CB 中使用它(例如,我在 2010 年使用过),但不受支持。我喜欢认为我通过当时与一些内部 Embarcadero 员工的一些对话鼓励它获得官方支持。 (我不知道我是否真的有任何影响 - 我只是喜欢这样想:)