2

次のようなクラスがあるとします。

class OProcess {
  ...
  void Process1();
  void Process2(); // call only if Process1 wasn't called
  ...
}

関数 Process2() は、関数 Process1() がまだ呼び出されていない場合にのみ呼び出すことができます。

コンパイル時に Process クラスが正しく使用されていることを確認する方法はありますか? つまり、 OProcess オブジェクトのインスタンスに対して Process2() の前に Process1() を呼び出すことができる場合、コンパイラはエラーを発生させる必要があります。

PS次のようなコードが存在する可能性があることを理解しています:

 if (variable == 1000)
   Process1();
 Process2();

コンパイラは、Process1() が Process2() の前に呼び出されることを確認できません。しかし、ここでコンパイラーは、変数のいくつかの値に対して Process2() の前に Process1() を呼び出すことができることを確認できます。そして、エラーまたは少なくとも警告を出すために必要です。

4

2 に答える 2

6

簡単な答えはSomewhatです。


長い答えは次のとおりです。C++ はLinear Typingを実装していないため、コンパイル時に (完全に) 一意性チェックを行うことはできません。それでも、この説明を読むとトリックがわかります。これをコンパイラに実装するために、言語設計者はエイリアシングを禁止し、消費を強制します。

したがって、いくつかの実行時チェックが許可されていることに同意する場合は、プロセスにオブジェクトを消費させることでこれを行うことができます。

class OProcess {
public:
};

std::unique_ptr<OProcessed1> process1(std::unique_ptr<OProcess> op);
std::unique_ptr<OProcess>    process2(std::unique_ptr<OProcess> op);

呼び出された後に許可された操作のみを公開する制限されたインターフェイスを提示するOProcessed1プロキシはどこにありますか。OProcessOProcessProcess1

チェックの実行時の部分は次のとおりです。

void func(std::unique_ptr<OProcess> op) {
    process1(std::move(op));
    process2(std::move(op));
}

op移動後に破棄/割り当て以外のことを行うのは未定義の動作ですが、コンパイルされます。

于 2013-11-02T14:44:25.703 に答える
0

それを行う正しい方法は、initをプライベートにして言及したリスクを軽減するか、依存性注入を使用することです。「init」メソッド、またはコンストラクター内のロジックは、クリーンなコードの点で悪い習慣です。

別のトリックは、コンストラクターでそれProcessBaseを定義initして呼び出すことです。のコンストラクターは派生コンストラクターの前に呼び出されるため、派生クラスでロジックが作成される前にProcessBase確実に呼び出されます。init

編集:

  • ロジックを変更して、両方のメソッドを非公開にし、1 つのメソッドprocess3()を呼び出して他のメソッドを正しい順序で呼び出すようにすることができます。
  • もう 1 つのオプションは、decoratorデザイン パターンを使用して 1 つのメソッドをクラスにラップし、デコレータにそれらを順番に呼び出させることです。
于 2013-11-02T14:23:09.313 に答える