在 C++Builder 中使用带有接口的通用 TList

Using Generic TList with Interfaces in C++Builder

如何在 C++Builder 中创建接口实例列表?我正在尝试以下操作,但编译器以不同的方式从每一个中抱怨:

#include <System.Generics.Collections.hpp>
...
TList__1<IInterface> IntfList;
TList__1<_di_IInterface> IntfList;
TList__1<DelphiInterface<IInterface>> IntfList;

另一方面,我也无法生成包含对象的列表。

TList__1<TObject> ObjList = new TList__1<TObject>();

所以我似乎很迷茫,而且文档也没有帮助

http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Generics.Collections.TList

或者是否有更好的替代方法?最终,我将需要一个数组,但我想使用 Add 动态构建它,然后从 IntfList->ToArray().

获取它

首先,TList<T> 是一个 Delphi TObject 派生的 class,所以它 必须 通过动态创建new 在 C++ 中,例如:

TList__1<T> *MyList = new TList__1<T>;
...
delete MyList;

其中T可以是_di_IInterfaceTObject*(注意*)等

现在,话虽这么说...

How can I create a list of interface instances in C++Builder?

简而言之,您无法通过 TList<T> 在纯 C++ 代码中单独执行此操作。这是记录在案的行为:

How to Handle Delphi Generics in C++

Delphi generics are exposed to C++ as templates. However, it is important to realize that the instantiations occur on the Delphi side, not in C++. Therefore, you can only use these template for types that were explicitly instantiated in Delphi code.

...

If C++ code attempts to use a Delphi generic for types that were not instantiated in Delphi, you'll get errors at link time.

原生 RTL 或 VCL/FMX 框架中没有 TList<IInterface> 的默认实例化。因此,您必须将自己的 Delphi 代码添加到 C++Builder 项目中才能创建此类实例,例如:

MyTListInstantiationUnit.pas

unit MyTListInstantiationUnit;

interface

{$HPPEMIT '#pragma link "MyTListInstantiationUnit"'} 

// or in XE5 Update 2 and later:
// {$HPPEMIT LINKUNIT}

implementation

uses
  System.Generics.Collections;

initialization
  TList<IInterface>.Create.Free;
finalization

end.

MyCppUnit.cpp

#include <System.Generics.Collections.hpp>
#include "MyTListInstantiationUnit.hpp"
...
TList__1<_di_IInterface> *IntfList = new TList__1<_di_IInterface>; // should work now

否则,您可以使用TInterfaceList代替:

#include <System.Classes.hpp>
...
TInterfaceList *IntfList = new TInterfaceList;
...
delete IntfList;

或者,如果您真的不需要跨 C++/Delphi 边界传递接口列表,则考虑使用像 std::vector 这样的纯 C++ 容器,例如:

#include <vector>
...
std::vector<_di_IInterface> IntfList;

至于TList<TObject>,它实际上确实存在于本机Delphi RTL 中,但它对您不起作用只是因为您没有正确使用它。它需要看起来更像这样:

TList__1<TObject*> *ObjList = new TList__1<TObject*>;
...
delete ObjList;

否则,您可以使用TObjectList代替,例如:

#include <System.Contnrs.hpp>
...
TObjectList *ObjList = new TObjectList;
...
delete ObjList;

或者,只需使用 std::vector<TObject*> 即可。