1

たとえば、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

4

3 に答える 3

3

これを必要以上に難しくしているようです。

#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、デストラクタでそれを削除し、メンバー関数acme_thingで型にキャストします::Thing*

于 2012-09-28T21:13:04.427 に答える
0

何かを別のものとまったく同じ名前にしようとするのは得策ではありません。(すべての名前空間を含む完全修飾名が等しいという意味です。) 一部のライブラリがグローバル名前空間で明らかな最適な名前を​​既に取得している場合は、別の名前を選択する必要があります。

Pete Becker が提案するように、クラスを名前空間に配置し、使用しAcmeの. 完全に名前空間で修飾された名前 (例: ) を介して常にクラスにアクセスする準備ができている場合は、それで問題ありません。orを試してみたくなるかもしれませんが、それはうまくいきません。クラスの定義を含む翻訳単位 (たとえば、作成したヘッダー ファイルを介して) は、最初に必ず Acme をグローバル名前空間にプルする必要があるためです(そうしないと、「未定義のシンボル」コンパイルの定義を解析するときにエラーが発生します)。Thing::ThingThingMy::Thingusing My::Thing;using namespace My;ThingMy::Thing

于 2012-09-28T21:40:25.710 に答える
-1

それは本当にCAPIですか?extern "C" {}リンクの問題を解決するために、含まれているヘッダー全体を試してください。

namespace AcmesUglyStuff {
  extern "C" {
    #include <acme_stuff.h>
  }
}
于 2012-09-28T21:05:54.767 に答える