如何将 C 结构包装在 C++ 类中并保持相同的名称

How to wrap a C struct in a C++ class and keep the same name?

本文关键字:结构 包装 C++      更新时间:2023-10-16

假设Acme公司发布了一个有用的库,其中包含一个极其丑陋的C API。我想将结构和相关函数包装在C++类中。 似乎我不能对包装类使用相同的名称,因为原始库不在命名空间内。

这样的事情是不可能的,对吧?

namespace AcmesUglyStuff {
    #include <acme_stuff.h>   // declares a struct Thing
}
class Thing {
 public:
    ...
 private:
    AcmesUglyStuff::Thing thing;
}; 

链接将是一个问题。

我能想到包装库而不用 C 库名称污染我的命名空间的唯一方法是像这样的黑客,在类中保留空间:

// In mything.h
namespace wrapper {
  class Thing {
   public:
    ...
   private:
    char impl[SIZE_OF_THING_IN_C_LIB];
  };
}
// In thing.cc
#include <acme_stuff.h>
wrapper::Thing::Thing() {
    c_lib_function((::Thing*)impl); // Thing here referring to the one in the C lib
}

这是唯一的办法吗? 我想避免在所有类名上加上前缀,例如XYThing等。

似乎你让这件事变得比它需要的更难。

#include "acme_stuff.h" // puts all of its names in global namespace
namespace acme {
class Thing {
public:
    // whatever
private:
    ::Thing thing;
};
}

现在只需使用acme::Thing而不是Thing

如果全局命名空间中没有 C 名称对您来说非常重要,那么您需要一个间接级别:

namespace acme {
class Thing {
public:
    Thing();
    ~Thing();
    // whatever
private:
    void *acme_thing;
};
}

在实现文件中,#include "acme_stuff.h" ,在构造函数中创建一个 new ::Thing 对象并将其地址存储在 acme_thing 中,在析构函数中删除它,并在成员函数中强制转换为::Thing*类型acme_thing

尝试将某些东西命名为与其他事物完全相同的东西不是一个好主意。 (我的意思是相等的完全限定名称,包括所有命名空间。 如果某个库已经在全局命名空间中获取了明显的最佳名称,则需要选择一个不同的名称。

你可以按照Pete Becker的建议将类Thing放在命名空间中,然后使用::Thing访问Acme的Thing。 如果您准备始终通过其完全命名空间限定的名称访问您的类(例如 My::Thing)。 尝试using My::Thing;using namespace My;很诱人,但这行不通,因为任何包含类定义的翻译单元(例如,通过您创建的头文件)都必须首先将 Acme 的Thing拉入全局命名空间(否则在解析 My::Thing 的定义时会发生"未定义的符号"编译错误)。

它真的是一个 C API 吗?尝试extern "C" {}整个包含的标题以解决链接问题。

namespace AcmesUglyStuff {
  extern "C" {
    #include <acme_stuff.h>
  }
}