当我在 C++ Builder 中创建简单项目并从我的包 - EhLib 中添加组件时,我收到下一个编译错误。
[bcc32c Error] Vcl.Buttons.hpp(66): reference to 'Vcl' is ambiguous
Vcl.Buttons.hpp(44): candidate found by name lookup is 'Vcl'
EhLib.VCL.hpp(48): candidate found by name lookup is 'Ehlib::Vcl'
我无法找出错误的原因。
在Delphi中创建类似的项目时,没有出现错误。
我使用 Embarcadero® RAD Studio 12 版本 29.0.53982.0329
我还无法制作一个最小的项目来重现该错误,因为 EhLib 包包含相当多的文件和代码。
我在EhLib.VCL.Hpp文件中发现了如下usingnamespace语句,但是我无法删除它,因为这个文件是系统根据pas文件自动生成的。
文件 EhLib.VCL.hpp
...
extern DELPHI_PACKAGE System::Types::TPoint __fastcall SafeGetMouseCursorPos(void);
extern DELPHI_PACKAGE System::UnicodeString __fastcall GetEhLibGUISysInfoAsString(void);
extern DELPHI_PACKAGE System::UnicodeString __fastcall GetEhLibFullSysInfoAsString(void);
} /* namespace Vcl */
} /* namespace Ehlib */
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB_VCL)
using namespace Ehlib::Vcl;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB)
using namespace Ehlib;
#endif
#pragma pack(pop)
#pragma option pop
#pragma delphiheader end.
我根本不在我的代码中使用 using 命名空间。所有usingnamespace语句都在自动生成的hpp文件中,不建议更改。
我无法添加整个源文件,因为 stackoverflow 将文本限制为 30,000 个字符,所以我只添加看起来重要的部分。
文件Unit1.cpp。我可以编辑的文件。
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "MemTableDataEh"
#pragma link "MemTableEh"
#pragma link "DBAxisGridsEh"
#pragma link "DBGridEh"
#pragma link "DBGridEhGrouping"
#pragma link "DBGridEhToolCtrls"
#pragma link "DynVarsEh"
#pragma link "EhLib.VCL"
#pragma link "GridsEh"
#pragma link "ToolCtrlsEh"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//
}
//---------------------------------------------------------------------------
文件Vcl.Buttons.hpp。我无法编辑这个文件。它是基础 VCL 库的一部分。
// CodeGear C++Builder
// Copyright (c) 1995, 2024 by Embarcadero Technologies, Inc.
// All rights reserved
// (DO NOT EDIT: machine generated header) 'Vcl.Buttons.pas' rev: 36.00 (Windows)
#ifndef Vcl_ButtonsHPP
#define Vcl_ButtonsHPP
#pragma delphiheader begin
#pragma option push
#if defined(__BORLANDC__) && !defined(__clang__)
#pragma option -w- // All warnings off
#pragma option -Vx // Zero-length empty class member
#endif
#pragma pack(push,8)
#include <System.hpp>
#include <SysInit.hpp>
#include <Winapi.Windows.hpp>
#include <Winapi.Messages.hpp>
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Graphics.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Winapi.CommCtrl.hpp>
#include <Vcl.ImgList.hpp>
#include <Vcl.Themes.hpp>
#include <System.UITypes.hpp>
#include <System.Generics.Collections.hpp>
#include <System.SysUtils.hpp>
#include <System.Generics.Defaults.hpp>
#include <System.Types.hpp>
#include <System.Actions.hpp>
#include <Vcl.Menus.hpp>
#include <Vcl.ActnList.hpp>
//-- user supplied -----------------------------------------------------------
#ifndef _WIN64
#pragma link "dwmapi.lib"
#endif //_WIN64
...
};
//-- var, const, procedure ---------------------------------------------------
extern DELPHI_PACKAGE void __fastcall (*FNavigatorEnableChanged)(TBaseNavigator* Self);
extern DELPHI_PACKAGE Winapi::Windows::TRect __fastcall DrawButtonFace(Vcl::Graphics::TCanvas* Canvas, const Winapi::Windows::TRect &Client, int BevelWidth, TButtonStyle Style, bool IsRounded, bool IsDown, bool IsFocused);
} /* namespace Buttons */
} /* namespace Vcl */
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_VCL_BUTTONS)
using namespace Vcl::Buttons;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_VCL)
using namespace Vcl;
#endif
#pragma pack(pop)
#pragma option pop
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // Vcl_ButtonsHPP
文件EhLib.VCL.hpp。我无法编辑这个文件。它是自动生成的。
// CodeGear C++Builder
// Copyright (c) 1995, 2024 by Embarcadero Technologies, Inc.
// All rights reserved
// (DO NOT EDIT: machine generated header) 'EhLib.VCL.pas' rev: 36.00 (Windows)
#ifndef EhLib_VCLHPP
#define EhLib_VCLHPP
#pragma delphiheader begin
#pragma option push
#if defined(__BORLANDC__) && !defined(__clang__)
#pragma option -w- // All warnings off
#pragma option -Vx // Zero-length empty class member
#endif
#pragma pack(push,8)
#include <System.hpp>
#include <SysInit.hpp>
#include <Vcl.Forms.hpp>
#include <System.SysUtils.hpp>
#include <Data.DB.hpp>
#include <System.TypInfo.hpp>
#include <Vcl.Controls.hpp>
#include <Winapi.Messages.hpp>
#include <System.Generics.Defaults.hpp>
#include <System.Generics.Collections.hpp>
#include <System.Classes.hpp>
#include <System.RTLConsts.hpp>
#include <Winapi.Windows.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Winapi.UxTheme.hpp>
#include <System.UITypes.hpp>
#include <EhLibUtils.hpp>
#include <DBUtilsEh.hpp>
#include <Vcl.ImgList.hpp>
#include <Vcl.Graphics.hpp>
#include <Vcl.Themes.hpp>
#include <System.Variants.hpp>
#include <System.Contnrs.hpp>
#include <System.StrUtils.hpp>
#include <System.Math.hpp>
#include <System.Types.hpp>
//-- user supplied -----------------------------------------------------------
namespace Ehlib
{
namespace Vcl
{
//-- forward type declarations -----------------------------------------------
class DELPHICLASS TWinControlEh;
class DELPHICLASS TCustomControlEh;
struct TDrawTextOptionsEh;
class DELPHICLASS TFilerAccess;
class DELPHICLASS TMemoryStreamEh;
//-- type declarations -------------------------------------------------------
typedef Data::Db::TBookmark TUniBookmarkEh;
...
extern DELPHI_PACKAGE System::Variant __fastcall RefObjectToVariant(System::TObject* ARefObject);
extern DELPHI_PACKAGE System::TObject* __fastcall VariantToRefObject(const System::Variant &VarValue);
extern DELPHI_PACKAGE System::Types::TPoint __fastcall SafeGetMouseCursorPos(void);
extern DELPHI_PACKAGE System::UnicodeString __fastcall GetEhLibGUISysInfoAsString(void);
extern DELPHI_PACKAGE System::UnicodeString __fastcall GetEhLibFullSysInfoAsString(void);
} /* namespace Vcl */
} /* namespace Ehlib */
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB_VCL)
using namespace Ehlib::Vcl;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB)
using namespace Ehlib;
#endif
#pragma pack(pop)
#pragma option pop
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // EhLib_VCLHPP
默认情况下,Pascal 生成的 HPP 标头将其 C++ 命名空间带入 HPP 文件的命名空间(通常是全局范围)。 而且由于两个
#include
命名空间都在同一范围内,编译器不知道要使用哪一个,因此会出现歧义错误。如果您仔细查看 HPP 文件,您会注意到那些 Vcl
语句包含在预处理器块中,例如:
using namespace
为了避免歧义,您可以在 C++ 项目设置的“条件定义”部分中指定
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_VCL_BUTTONS)
using namespace Vcl::Buttons;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_VCL)
using namespace Vcl;
#endif
或所需的
DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE
条件。 或者,至少,只需将 NO_USING_NAMEPACE_...
放在 C++ 代码中的相关 #define
语句上方即可。另一种解决方法是将 #include
添加到您的 Pascal 单位,以避免生成的 HPP 文件中出现任何
{$HPPEMIT NOUSINGNAMESPACE}
语句。