How to "track" missing ctor initialization list arguments?

I'm sure everyone has time to get distracted.

The problem is adding another field to the class and forgetting the extension of the initialization list, for example:

class T{ private: field1; ... field10; }; T::T( int speedValue ): field1( Speed::MphToMps(speedValue) ), field2( new OtherClass(14,5,15) ), field3( PublicValueGenerator::generateNewFieldValue(0,15) ), ..., field10( "unpredictable value" ); 

And if in a hurry I add some kind of field, say newForgottenField, from time to time I forget to set the value to init. As I recall, some IDEs can give a hint, but vim + addons is my choice :)

So, mb has some hint to simplify tracking such situations or some kind of thumb rule or rough macros that give a warning or compile-time error (that would be awesome :))? How do you overcome this obstacle?

Best wishes

+4
source share
4 answers

If you use g ++, then it provides an option that allows you to warn about constructs that violate recommendations in Scott Meyer Effective C ++ :)
Option:

 -Weffc++ 

Note that it will also include a number of other warnings. In addition, not all standard library headers follow the Meyers guild.

+6
source

One way to get what you want is to make sure that all of your fields are instances of classes that either have a default constructor that does what is needed, or only have constructors that require arguments.

This is not always convenient, but it will certainly solve your problem.

+1
source

This is a good question, and it would be useful to be able to easily check, but in general C ++ solutions can actually support a combination of errors, verbosity, and obfuscation, which makes them more tedious than the problem of trying to solve. However - for the sake of discussion - there are several approaches to this ...

You can create a class that does not have a default constructor:

 template <typename T> class Explicitly_Initialised { public: Explicitly_Initialised(const T& t) : t_(t) { } T& operator T() { return t_; } const T& operator T() const { return t_; } private: T t_; }; 

Or you may have a class that issues if the object is read before it is assigned a value (perhaps only in "debug" assemblies, if you have such a concept). You can decide if the value from operator= was ok. You will need a member bool has_been_initialised_; to track this parameter, set false in the default constructor. One of the problems would be that operator T() does not know if the variable should be read before it is written, so to do the thorough work, you may need a proxy object to manage this situation: painful.

Alternatively, and too messy to actually recommend — you could hack a class that accepted a list of types, had a member object for each of these types, and insisted on matching the list in the constructor; it would be difficult to allow this generic class to accept ordinary arbitrary identifiers for accessing data members (it is easy to allow numerical access or even access to a type if the types were unique) (perhaps you could make it work with macro hackers).

0
source

The easiest way to solve this problem in C ++ 11 is to provide element initializers for all primitive elements:

 class T { private: int field1{}; ... int field10{}; }; 
0
source

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


All Articles