【问题标题】:Use TDictionary in C++ Builder XE2在 C++ Builder XE2 中使用 TDictionary
【发布时间】:2012-05-16 03:26:10
【问题描述】:

目前我想在 C++ Builder XE2 中使用TDitionary

阅读documentation 后,我认为这应该很容易,但我什至无法创建TDictionary 对象...

我的代码:

#include <vcl.h>
#pragma hdrstop
#include <Generics.collections.hpp>
#include "TDictionaryTest.h"

#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;

void __fastcall TForm2::FormCreate(TObject *Sender)
{
    TDictionary__2 <String, String> *Dir = new  TDictionary__2<String, String>(0);
    delete Dir;
}

错误信息:

[ILINK32 Error] Error: Unresolved external '__fastcall           System::Generics::Collections::TDictionary__2<System::UnicodeString,   System::UnicodeString>::~TDictionary__2<System::UnicodeString, System::UnicodeString>()'  referenced from ...\PRACTICE\C++\WIN32\DEBUG\TDICTIONARYTEST.OBJ
[ILINK32 Error] Error: Unresolved external '__fastcall System::Generics::Collections::TEnumerable__1<System::Generics::Collections::TPair__2<System::UnicodeString, System::UnicodeString> >::~TEnumerable__1<System::Generics::Collections::TPair__2<System::UnicodeString, System::UnicodeString> >()' referenced from ...\PRACTICE\C++\WIN32\DEBUG\TDICTIONARYTEST.OBJ
[ILINK32 Error] Error: Unresolved external 'System::Generics::Collections::TDictionary__2<System::UnicodeString, System::UnicodeString>::' referenced from ...\PRACTICE\C++\WIN32\DEBUG\TDICTIONARYTEST.OBJ
[ILINK32 Error] Error: Unresolved external '__fastcall System::Generics::Collections::TDictionary__2<System::UnicodeString, System::UnicodeString>::TDictionary__2<System::UnicodeString, System::UnicodeString>(int)' referenced from ...\PRACTICE\C++\WIN32\DEBUG\TDICTIONARYTEST.OBJ
[ILINK32 Error] Error: Unable to perform link

有人知道吗?谢谢!

【问题讨论】:

    标签: c++ dictionary c++builder c++builder-xe2


    【解决方案1】:

    就像@mhtaqia 所说,C++ 还不能实例化 Delphi 的泛型类,只有在 Delphi 代码创建它们时才使用它们。对于 C++ 代码,您应该改用 STL std::map

    #include <map> 
    
    void __fastcall TForm2::FormCreate(TObject *Sender) 
    { 
        std::map<String, String> *Dir = new std::map<String, String>; 
        delete Dir; 
    } 
    

    或者:

    #include <map> 
    
    void __fastcall TForm2::FormCreate(TObject *Sender) 
    { 
        std::map<String, String> Dir; 
    }
    

    附带说明:切勿在 C++ 中使用 TForm::OnCreateTForm::OnDestroy 事件。它们是 Delphi 惯用语,可以在 C++ 中产生非法行为,因为它们可以分别在派生构造函数之前和派生析构函数之后触发。请改用实际的构造函数/析构函数。

    【讨论】:

    • @Remy OnCreate 与 C++ 构造函数或 Delphi 构造函数无关。在 VCL 应用程序中,总是首先调用类构造函数。当 VCL 在表单上创建所有 VCL 组件时,将调用 OnCreate 事件处理程序。您应该始终在此处使用和初始化表单的 VCL 组件,而不是在类构造函数中。当您仍然可以访问所有 VCL 组件时,在类析构函数之前调用的 OnDestroy 也是如此。然后调用类析构函数。但是你不应该自己调用 OnCreate 和 OnDestroy,也许这就是你的意思;)
    • 错了。 Form 的OnCreate 事件触发与C++ 类构造函数相关的顺序,以及OnDestroy 事件与C++ 类析构函数相关的触发顺序,与Form 的OldCreateOrder 属性直接相关。当OldCreateOrder 为真时,OnCreate 事件在 C++ 构造函数之前触发,OnDestroy 在 C++ 析构函数之后触发。这两个事件都由TCustomForm 基类触发。这就是我所指的非法行为——基类构造函数/析构函数以非法顺序调用派生类方法。
    • 这在 Delphi 中是允许的,因为 Delphi 使用的对象创建模型的顺序与 C++ 的创建模型相反。 Delphi 以 Derived->Base 顺序构造对象,但 C++ 以 Base->Derived 顺序构造对象。所有 VCL 对象都遵循 Delphi 创建顺序,即使在 C++ 代码中实例化时也是如此。它们不遵循 C++ 创建模型。这就是 TCustomForm 可以调用派生 Form 的 OnCreate/Destroy 事件的方式,但这种行为在 C++ 中是非法的。
    • 这种情况在 C++ 中是可能的,因为 OldCreateOrder 属性很奇怪。即使您在设计时将其设置为 false,它也会在运行时意外地将自身切换为 true。因此,您最终可以访问尚未构建或已被释放的数据。这不是猜测。历史表明,这种情况过去在现实世界的应用程序中已经发生过很多次。这就是为什么在 C++ 中使用 OnCreate/OnDestroy 事件是危险的。完全避免它们并使用 C++ 构造函数/析构函数。
    • 最后,即使Embarcadero's own documentation 也这么说:“注意:在 C++ 代码中不鼓励使用 OnCreate 事件,因为它可能与表单的构造函数交互不良(请参阅 OldCreateOrder)。建议您而是覆盖表单构造函数。”
    【解决方案2】:

    TDictionary 仅用于访问 Delphi 变量和字段。您不能在 C++ 代码中使用和实例化它。模板类在完全定义在头文件中时可用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 2012-12-02
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多