Defining a private integral constant of a class: in the header or in the cpp file?

The topic was discussed mainly here ( Where to declare / define class region constants in C ++? ) And in particular here .

What I would like to fully understand, in the case of integral constants, there is some difference between:

//In the header class A { private: static const int member = 0; //Declaration and definition }; 

and

 //In the header class A { private: static const int member; //Only declaration }; //In the cpp const int A::member = 0; //Definition 

(I understand that the second may have the advantage that if I change the value of the constant, I will have to recompile only one file)

Side questions:
What happens, for example, with the built-in method defined in the header that calls member ? Would it just not be nested? What happens if, going to one extreme, all methods were defined in the header file as built-in methods, and all the constants were defined in the cpp file?

Edit:

I apologize: I thought this was optional, but I missed the fact that the member is static. My question remains, but now the code is legal.

+6
source share
3 answers

If, as it was before the question was changed to make it static, it is a non-static member, then it can only be initialized in the list of constructor initializers or (starting in 2011) in the participant declaration. Your second example was poorly formed.

If it is static, you need a definition if it is used by odr: roughly speaking, if you are doing something that requires its address, and not just its value. If you use only value, then the first example will be fine. But keep in mind that the comment is incorrect - it's just an announcement, not a definition.

If you need a definition, it depends on whether you specify a value in the declaration or definition. Specifying it in the declaration allows you to improve the scope of optimization, since the value is always available when using a variable. Specifying it in the definition gives the best encapsulation, requiring that only one translation unit be recompiled if it has changed.

What happens, for example, with the built-in method defined in the header that has access to the member? Would it just not be nested?

There is no reason why access to a data object defined in another translation module should prevent the function from being built in.

+6
source

This is a data hiding question. Do you want to open the internal fields of the class or not. If you send a class library and want to hide implementation details, it is better to show as few entities as possible in the interface, then even the declaration of the private member field is too large.

I would just declare this value as a static variable inside the .cpp file.

+3
source

There are two points of view that need to be considered, namely: visibility and addressing.

Note that these two are orthogonal, since you can actually declare the variable as initialized and still define it in the translation block to have an effective memory address.

Visibility

Visibility affects the use of a variable and has some technical implications.

For use in a template as a parameter of a non-type type template, the value must be visible at the point of use. Also, in C ++ 11, this may be required to use constexpr . Otherwise, this value is not required to be visible.

Technically visible value can trigger optimization from the compiler. For example, if (A::member) is trivially false, so the check can be eliminated. This is usually called continuous distribution. Although this may seem successful, at first glance there is a profound effect: all clients of the header file are potentially dependent on this value, and thus, any change to this value means that they must be recompiled. If you deliver this header as part of a shared library, it means that changing this value aborts the ABI.

Decision

The rule here is quite simple: if the variable can be addressed (either passed by pointer or by reference), then it must be somewhere in memory. This requires a definition in one translation unit.

+2
source

Source: https://habr.com/ru/post/951373/


All Articles