简体   繁体   English

初始化const成员变量

[英]Initialize const member variables

I have C++ code that boils down to something like the following: 我有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);
}

Semantically, the bar and baz member variables should be const, since they should not change after initialization. 从语义上讲,bar和baz成员变量应该是const,因为它们在初始化后不应该更改。 However, it seems that in order to make them so, I would need to initialize them in an initialization list rather than assign them. 但是,似乎为了使它们如此,我需要在初始化列表中初始化它们而不是分配它们。 To be clear, I understand why I need to do this. 要清楚,我理解为什么我需要这样做。 The problem is, I can't seem to find any way to convert the code into an initialization list without doing one of the following undesirable things: 问题是,我似乎无法找到任何方法将代码转换为初始化列表而不执行以下不良操作之一:

  • Call complex_method twice (would be bad for performance) 调用complex_method两次(对性能complex_method
  • Add the pointer to the Foo class (would make the class size needlessly large) 将指针添加到Foo类(会使类大小不必要地变大)

Is there any way to make the variables const while avoiding these undesirable situations? 有没有办法让变量const同时避免这些不良情况?

If you can afford a C++11 compiler, consider delegating constructors : 如果您能负担得起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)}
{
}

As a general advice, be careful declaring your data members as const , because this makes your class impossible to copy-assign and move-assign. 作为一般建议,请小心将数据成员声明为const ,因为这会使您的类无法复制 - 分配和移动 - 分配。 If your class is supposed to be used with value semantics, those operations become desirable. 如果您的类应该与值语义一起使用,那么这些操作将变得可取。 If that's not the case, you can disregard this note. 如果情况并非如此,您可以忽略此说明。

One option is a C++11 delegating constructor, as discussed in other answers. 一个选项是C ++ 11委托构造函数,如其他答案中所述。 The C++03-compatible method is to use a subobject: 与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))
{}

You can make bar and baz const, or make the subobject const, or both. 您可以使barbaz const,或使subobject const,或两者。

If you make only subobject const, then you can calculate complex_method and assign to bar and baz within the constructor of subobject : 如果只生成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);
}

The reason that you can't mutate const members within a constructor body is that a constructor body is treated just like any other member function body, for consistency. 您不能在构造函数体内改变const成员的原因是构造函数体被视为与任何其他成员函数体一样,以保持一致性。 Note that you can move code from a constructor into a member function for refactoring, and the factored-out member function doesn't need any special treatment. 请注意,您可以将代码从构造函数移动到成员函数中进行重构,并且分解成员函数不需要任何特殊处理。

You may use delegate constructor in C++11: 您可以在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;
};

If you don't want to use the newfangled delegating constructors (I still have to deal with compiler versions that don't know about them), and you don't want to change the layout of your class, you could opt for a solution that replaces the constructor with const void * argument by a static member function returning Foo , while having a private constructor that takes the output from complex_method as argument (that latter much like the delegating constructor examples). 如果您不想使用newfangled委托构造函数(我仍然需要处理不了解它们的编译器版本),并且您不想更改类的布局,则可以选择解决方案用一个返回Foo的静态成员函数替换带有const void *参数的构造函数,同时有一个私有构造函数,它将complex_method的输出作为参数(后者很像委托构造函数示例)。 The static member function then does the necessary preliminary computation involving complex_method , and ends with return Foo(s); 静态成员函数然后执行涉及complex_method的必要初步计算,并以return Foo(s); . This does require that the class have an accessible copy constructor, even though its call (in the return statement) can most probably be elided. 这确实要求类具有可访问的复制构造函数,即使它的调用(在return语句中)很可能被省略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM