Initialize const member variables

后端 未结 4 1868
逝去的感伤
逝去的感伤 2021-01-01 11:47

I have C++ code that boils down to something like the following:

class Foo{
    bool bar;
    bool baz;
    Foo(const void*);
};
Foo::Foo(const void* ptr){
          


        
相关标签:
4条回答
  • 2021-01-01 12:04

    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). The static member function then does the necessary preliminary computation involving complex_method, and ends with 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.

    0 讨论(0)
  • 2021-01-01 12:05

    You may use delegate constructor in 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;
    };
    
    0 讨论(0)
  • 2021-01-01 12:15

    If you can afford a C++11 compiler, consider delegating constructors:

    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. 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.

    0 讨论(0)
  • 2021-01-01 12:24

    One option is a C++11 delegating constructor, as discussed in other answers. The C++03-compatible method is to use a subobject:

    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.

    If you make only subobject const, then you can calculate complex_method and assign to bar and baz within the constructor of subobject:

    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. 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.

    0 讨论(0)
提交回复
热议问题