24

次のようなものに要約される C++ コードがあります。

class Foo{
    bool bar;
    bool baz;
    Foo(const void*);
};
Foo::Foo(const void* ptr){
    const struct my_struct* s = complex_method(ptr);
    bar = calculate_bar(s);
    baz = calculate_baz(s);
}

意味的には、bar および baz メンバー変数は、初期化後に変更されるべきではないため、const である必要があります。ただし、そのようにするには、割り当てるのではなく、初期化リストで初期化する必要があるようです。明確にするために、なぜこれを行う必要があるのか​​ を理解しています。問題は、次の望ましくないことのいずれかを行わずに、コードを初期化リストに変換する方法が見つからないように見えることです。

  • 2 回呼び出すcomplex_method(パフォーマンスが低下する可能性があります)
  • Foo クラスへのポインターを追加します (クラスのサイズが不必要に大きくなります)。

これらの望ましくない状況を回避しながら、変数を const にする方法はありますか?

4

4 に答える 4

12

他の回答で説明されているように、1 つのオプションは C++11 委任コンストラクターです。C++03 互換の方法は、サブオブジェクトを使用することです。

class Foo{
    struct subobject {
        const bool bar;
        const bool baz;
        subobject(const struct my_struct* s)
            : bar(calculate_bar(s))
            , baz(calculate_baz(s))
        {}
    } subobject;
    Foo(const void*);
};
Foo::Foo(const void* ptr)
    : subobject(complex_method(ptr))
{}

make とconst、 makebarとconst、またはその両方を行うことができます。 bazsubobject

constのみを作成すると、 のコンストラクター内で計算して代入subobjectできます。complex_methodbarbazsubobject

class Foo{
    const struct subobject {
        bool bar;
        bool baz;
        subobject(const void*);
    } subobject;
    Foo(const void*);
};
Foo::Foo(const void* ptr)
    : subobject(ptr)
{}
Foo::subobject::subobject(const void* ptr){
    const struct my_struct* s = complex_method(ptr);
    bar = calculate_bar(s);
    baz = calculate_baz(s);
}

コンストラクター本体内でメンバーを変更できない理由は、一貫性のconstために、コンストラクター本体が他のメンバー関数本体と同じように扱われるためです。リファクタリングのためにコードをコンストラクターからメンバー関数に移動できます。また、分解されたメンバー関数は特別な処理を必要としません。

于 2015-01-19T18:08:10.610 に答える