1

クラス定義を効果的にファイナライズする (サブクラス化を防ぐ) マクロを、クラス定義の周りに追加することができます。このファイナライズ方法はかなり一般的な手法であり、C++ FAQに記載されています。

#define FINALIZE(NAME,...) \
    NAME##Finalizer {\
        private:\
            friend class NAME;\
            inline NAME##Finalizer(void) {}\
    };\
    class NAME : public virtual NAME##Finalizer, __VA_ARGS__

例えば:

class FINALIZE(Fred) {};
//The above line evaluates to:
//  class FredFinalizer {
//      private:
//          friend class Fred;
//          inline FredFinalizer(void) {}
//  };
//  class Fred : public virtual FredFinalizer, {};

class George {};
class FINALIZE(Fred2, public George) {};
//The above line evaluates to:
//  class Fred2Finalizer {
//      private:
//          friend class Fred2;
//          inline Fred2Finalizer(void) {}
//  };
//  class Fred2 : public virtual Fred2Finalizer, public George {};

class Velma : public Fred { Velma(void) {} /*Note compile error*/ };
class Velma2 : public Fred2 { Velma2(void) {} /*Note compile error*/ };

これは見事に機能します。問題は、マクロを「無効にする」方法が欲しいということです。あれは:

class FINALIZE(Fred) {};
//The above line evaluates to:
//  class Fred {};

class George {};
class FINALIZE(Fred2, public George) {};
//The above line evaluates to:
//  class Fred2 : public George {};

問題は、class Fred2 : public George {};継承がない場合 ( ) と衝突することclass Fred {};です。最初のケースでは常にコロンが必要であり、2 番目のケースではコロンがあってはなりません。クラスは少なくともNAME##Finalizer クラスから常に継承されるため、マクロが有効になっている場合、これは問題ではないことに注意してください。

これを行うマクロを作成するにはどうすればよいですか?

4

1 に答える 1

1

2つのマクロを作成することをお勧めします。1つはファイナライザーの準備用、もう1つは使用用です。

#define PREP_FINALIZE(NAME) \
    class NAME##Finalizer {\
        private:\
            friend class NAME;\
            inline NAME##Finalizer() {}\
    }

#define FINALIZE(NAME) virtual NAME##Finalizer

したがって、あなたの例では:

PREP_FINALIZE(Fred);
class Fred : FINALIZE(Fred) {};

class George {};
PREP_FINALIZE(Fred2);
class Fred2 : FINALIZE(Fred2), public George {};

しかし、コピーコンストラクターをプライベートにすることを忘れてしまうことがより重要です。それがなければ、あなたのやり方は非常に簡単に浮気する可能性があります:

// cheating :D
class Velma : public Fred, FINALIZE(Fred) { 
   Velma() : FredFinalizer(*(FredFinalizer*)0) {} /*Who said this is compiler error */ 
};

ファイナライザーのコピーコンストラクターをプライベートにします。または、非常によく似た質問に対する私の答えを使用してください。

C ++ 11の場合は、finalを使用してください;)

于 2012-09-15T20:54:13.200 に答える