2

クラスの外部でプライベートデータの一部を覗き見するために使用することを目的としたアクセサメソッドを持つクラスがあります。

ただし、クラスの内部状態は他のメソッドによって変更され、これらの変更は計算が完了するまでパブリックアクセサーが参照する場所に書き込まれないため、クラスの内部メソッドはこれらのパブリックアクセサーを使用しないでください。

クラスが1つ以上の独自のメンバーを呼び出さないようにするコンパイル時の手段はありますか?assertまたは、リリースのコンパイルで簡単に削除できるため、を使用した実行時チェックは問題ありません。

4

2 に答える 2

2

While I have never seen this pattern in practice, you could separate implementation and interface (though it is normally the other way around)

namespace detail {
    class Impl {
    protected:
        Impl() : x_(0) {}

        int x_;
        void internal() { x_ = 1; }
        void something_else() { x_ = 2; }
    };
}

class Interface : public detail::Impl {
public:
    int x() const { return x_; }
    void x(int x) { x_ = x; }
};

Or a step further without derivation:

class Interface;

namespace detail {
    class Impl {
    private:
        friend class ::Interface;
        Impl() : x_(0) {}

        int x_;
        void internal() { x_ = 1; }
        void something_else() { x_ = 2; }
    };
}

class Interface {
public:
    int x() const { return impl_.x_; }
    void x(int x) { impl_.x_ = x; }
private:
    Impl impl_;
};

Also lookup the PIMPL idiom, which is often used to reduce header/library/client coupling and to increase compile times.

于 2013-01-26T13:05:42.213 に答える
0

アサーションを使用したデバッグ ビルドに関する私の提案は次のとおりです。

  • という単純な関数またはマクロを作成しIncrementInternalCallCountます。これにより、クラス内の呼び出し回数が増加します。このためには、クラスにカウンター変数を用意してください。このようなものは、デバッグ/診断目的でのみ配置してください。
  • このマクロ/関数への呼び出しを、クラスのすべてのメソッドに配置します。それらのゲッター関数を除きます。
  • getter 関数で、internal-call-count が 0 より大きいかどうか、および 0 であるかどうかを確認します。アサーションを提起します。

このために、カウンターをインクリメントし、関数の終了時にカウンターをデクリメントするいくつかの RAII クラスを使用できます。したがって、すべての関数の先頭に RAII オブジェクトを配置する必要があります。デストラクタは自動的に呼び出されます。これにより、ゲッター以外のすべての関数を他のクラス関数から呼び出すこともできます。

非常に最小限のコード (厳密には C++ ではありません):

class CYourClass
{
    int Counter = 0; // Not C++ syntax

   IncrementCallCounter() { Counter++;}
   DecrementCallCounter() { Counter++;}
   CheckCounterStatus() { if(Counter>0) ASSERT;}

private:
   void InternalFun() 
  {
     IncrementCallCounter();
    // Do work, call anything
    DecrementCallCounter();
  }

public:
int Getter1()
{
   CheckCounterStatus();
}
};
于 2013-01-26T12:59:41.983 に答える