3

foobar次の使用法で、その下に定義されたクラスのグローバル オブジェクトを定義するマクロを書きたいと思います。

SOMEMACRO(foobar)
{
public:
   int a;
};

言い換えれば、上記が次と同じ効果を持つことを望みます:

class SomeClassPossiblyWith_foobar_InItsName
{
public:
   int a;
};
SomeClassPossiblyWith_foobar_InItsName foobar;

オブジェクトに「foobar」という名前を正確に付ける (または、少なくともそのような方法で適切なオブジェクトへの参照を呼び出す) ことは非常に重要です。マクロを複数回使用できる限り、クラスの名前は問題ではありません。

クラスは通常、使用する前に定義する必要があるため、かなり難しいですが、それを達成するためのトリッキーな (おそらくテンプレートが関与する) 方法が存在するのではないでしょうか?

4

4 に答える 4

1

あなたはこのようにすることができます:

#define SING(classname, body) class SING_##classname \
body \
; SING_##classname classname;

次に、次のように使用します。

SING (foobar, {
    public:
        int a;
    }
);
于 2013-02-03T21:47:20.370 に答える
1

プリプロセッサの連結演算子を使用すると、非常に簡単##です。

何かのようなもの:

#define SOMEMACRO(name) \
SomeClassPossiblyWith_##name##_InItsName name; \
class SomeClassPossiblyWith_##name##_InItsName
于 2013-02-03T19:55:09.987 に答える
1

私はしばらくの間、参照を作成し、適切なオブジェクトで初期化する解決策を見つけました。これは、どういうわけか質問に答えます。それが標準的な苦情であるかどうかはわかりません(gcc 4.6に準拠しています)。

template<typename T>
T &delayed_make_object()
{
    static T obj;
    return obj;
}

#define DOIT(_name) \
    class TypeFor ## _name; \
    TypeFor ## _name & _name = delayed_make_object<TypeFor ## _name>(); \
    class TypeFor ## _name


DOIT(foo)
{
    public:
    int abc;
};  

DOIT(bar)
{
    public:
    int cba;
};

int main()
{
  foo.abc=bar.cba;   // works!
}
于 2013-02-03T21:46:20.227 に答える
0

編集:コードに説明を追加しました。

テンプレートを使用したソリューションは次のようになります。

作成時にグローバル アクセスを持つインスタンスを持つ必要があるクラスのテンプレートを作成しました。これがあなたの望むものだと思います。(名前のデザインパターンを参照してSingletonと名付けました) .h:

// C++ header for template Singleton
template<typename T>
class Singleton : public T {
    static Singleton<T>* instance;
    Singleton();
public:
    static Singleton<T>* getInstance();
};

getInstance() メソッドは、そのインスタンスを取得する場所からのものになります。ポインターの代わりにオブジェクトにすることもできますが、実行時にインスタンスを変更するなど、より複雑なことをしたい場合に汎用性が高いため、この方法の方が気に入っています。また、使用時にのみオブジェクトをインスタンス化できるため、メモリ割り当てが不要になります。.cpp:

// C++ source for template Singleton
template<typename T>
Singleton<T>* Singleton<T>::instance = NULL;

template<typename T>
Singleton<T>::Singleton()
: T()
{}

template<typename T>
Singleton<T>* Singleton<T>::getInstance()
{
    if (instance == NULL)
    {
        instance = new Singleton<T>();
    }
    return instance;
}

必要な任意のクラスを通常どおり実装し、Singleton テンプレートを使用して、特定のクラスの同じグローバル インスタンスを常に処理できるようにすることができます。必要に応じて、typedef を使用して型名を定義することもできます。あなたのクラス定義:

// Definition of class foobar
class foobar_impl {
public:
    int a;
};

typedef Singleton<foobar_impl> Foobar;

次に、テンプレートを使用して foobar_impl のインスタンスを取得します。

int main(int argc, char** argv)
{
    Foobar *pf = Foobar::getInstance();
    return 0;
}

ただし、このソリューションの問題は、Singleton テンプレートが空のコンストラクターを持つクラスでのみ機能することです。しかし、あなたの例もそうなので、これがあなたが望むものだと思います。

于 2013-02-03T22:10:37.497 に答える