簡體   English   中英

初始化const成員變量

[英]Initialize const member variables

我有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,因為它們在初始化后不應該更改。 但是,似乎為了使它們如此,我需要在初始化列表中初始化它們而不是分配它們。 要清楚,我理解為什么我需要這樣做。 問題是,我似乎無法找到任何方法將代碼轉換為初始化列表而不執行以下不良操作之一:

  • 調用complex_method兩次(對性能complex_method
  • 將指針添加到Foo類(會使類大小不必要地變大)

有沒有辦法讓變量const同時避免這些不良情況?

如果您能負擔得起C ++ 11編譯器,請考慮委托構造函數

class Foo
{
    // ...
    bool const bar;
    bool const baz;
    Foo(void const*);
    // ...
    Foo(my_struct const* s); // Possibly private
};

Foo::Foo(void const* ptr)
    : Foo{complex_method(ptr)}
{
}

// ...

Foo::Foo(my_struct const* s)
    : bar{calculate_bar(s)}
    , baz{calculate_baz(s)}
{
}

作為一般建議,請小心將數據成員聲明為const ,因為這會使您的類無法復制 - 分配和移動 - 分配。 如果您的類應該與值語義一起使用,那么這些操作將變得可取。 如果情況並非如此,您可以忽略此說明。

一個選項是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))
{}

您可以使barbaz const,或使subobject const,或兩者。

如果只生成subobject const,則可以計算complex_method並在subobject的構造函數中指定barbaz

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成員的原因是構造函數體被視為與任何其他成員函數體一樣,以保持一致性。 請注意,您可以將代碼從構造函數移動到成員函數中進行重構,並且分解成員函數不需要任何特殊處理。

您可以在C ++ 11中使用委托構造函數:

class Foo{
public:
    Foo(const void* ptr) : Foo(complex_method(ptr)) {}

private:
     Foo(const my_struct* s) : bar(calculate_bar(s)), baz(calculate_baz(s)) {}

private:
    const bool bar;
    const bool baz;
};

如果您不想使用newfangled委托構造函數(我仍然需要處理不了解它們的編譯器版本),並且您不想更改類的布局,則可以選擇解決方案用一個返回Foo的靜態成員函數替換帶有const void *參數的構造函數,同時有一個私有構造函數,它將complex_method的輸出作為參數(后者很像委托構造函數示例)。 靜態成員函數然后執行涉及complex_method的必要初步計算,並以return Foo(s); 這確實要求類具有可訪問的復制構造函數,即使它的調用(在return語句中)很可能被省略。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM