【问题标题】:global scope enum and namespace conflict全局范围枚举和命名空间冲突
【发布时间】:2013-04-13 08:36:27
【问题描述】:

我有一个 ATL COM 服务,在 .IDL 文件中,我声明了一个枚举,如下所示:

在 Gourmet.idl 中

typedef enum Food
{
    Chocolate = 0,
    Doughnut,
    HotDog
} Food;

会自动生成一个头文件,创建 Gourmet_i.h。

在同一个 ATL COM 项目的另一个 .CPP 文件(我们称之为 Decadence.cpp)中,我 #include Gourmet_i.h。我在这个 .CPP 中实现了一个类,它位于命名空间“Chocolate”下。

例如在 Decadence.cpp 中:

#include "Gourmet_i.h"

namespace Chocolate {

// Constructor
void Decadence::Decadence() {}

// ... and so on

} // namespace Chocolate

编译时我收到以下关于 Gourmet_i.h 的错误:

error C2365: 'Chocolate': redefinition; previous definition was 'namespace'

我看到这是因为 IDL 的枚举是在全局命名空间中定义的,但是是否可以包含这个定义——因此它不会污染全局命名空间——而且我不会有这个冲突?

【问题讨论】:

  • typedef 的意义何在?这不是 C。在 C++ 中,标签查找是自动执行的,无需指定 enumstruct

标签: c++ com enums atl midl


【解决方案1】:

没有重命名命名空间或枚举成员,唯一的解决方案是将生成的头文件的内容包装在命名空间中。这并非没有陷阱,并且取决于 MIDL 文件的内容,它最终可能会引起一些麻烦。我能看到的最简洁的方法是创建一个代理头文件,声明命名空间,然后包含 MIDL 生成的头文件。

Gourmet.h

namespace MIDLStuff
{
    #include "Gourmet_i.h"
}

【讨论】:

  • 这似乎是最干净的方法。为我工作。顺便说一句,我将开始远离在 COM 接口中声明枚举。
  • @ykay:是否在 IDL 中声明枚举不应受此问题的影响。如果定义使用枚举的方法,则需要在接口中使用枚举。有些人选择将枚举成员命名为fdChocolatefdDoughnut 等。这可能对您有用。枚举成员没有作用域的事实是 C 的一个怪癖(并且由 C++ 继承),而不是 IDL 的错。
【解决方案2】:

如果您使用的是 C++11,则可以通过包含 class 来使用范围枚举:

typedef enum class Food
{
    Chocolate = 0,
    Doughnut,
    HotDog
} Food;

现在你需要在使用值时写Food::Chocolate

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 2011-01-16
    • 2021-10-15
    • 2012-03-16
    • 1970-01-01
    相关资源
    最近更新 更多