0

In a class that looks somehow like this:

MyClass.h

class MyClass{

public:
    MyClass();
    int x1;
    int x2;
    int x3;
    int x4;
    int x5;

private:
    int y1;
    int y2;
};

MyClass.cpp

#include "MyClass.h"

int someFunc1(int x1, int x2){
    return x1+x2;
}

int someFunc2(int x1, int x2){
    return x1+x2;
}

MyClass::MyClass(): 
    x1(1), x2(2), x3(3), x4(4),
    y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2){}

main.cpp

#include "MyClass.h"

int main(int argc, char **argv)
{

    MyClass myclass;

    return 0;
}

Compiler's outputs:

In file included from MyClass.cpp:1:
MyClass.h: In constructor ‘MyClass::MyClass()’:
MyClass.h:13:9: warning: ‘MyClass::y2’ will be initialized after [-Wreorder]
     int y2;
         ^~
MyClass.h:9:9: warning:   ‘int MyClass::x5’ [-Wreorder]
     int x5;
         ^~
MyClass.cpp:11:1: warning:   when initialized here [-Wreorder]
 MyClass::MyClass():
 ^~~~~~~
MyClass.cpp: In constructor ‘MyClass::MyClass()’:
MyClass.cpp:13:54: warning: ‘*<unknown>.MyClass::y1’ is used uninitialized in this function [-Wuninitialized]
     y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2){}
                                                      ^~
MyClass.cpp:13:57: warning: ‘*<unknown>.MyClass::y2’ is used uninitialized in this function [-Wuninitialized]
     y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2){}
                                                         ^~

I'm not in control of someFunc1 and someFunc2, I just defined them in that way to get the code compiled.

I can fix these warnings by getting rid of member-initializer list, and initialize the data members in constructor's body like this:

MyClass::MyClass(){
    x1 = 1;
    x2 = 2;
    x3 = 3;
    x4 = 4;
    y1=someFunc1(x1, x2); 
    y2=someFunc2(x3, x4);
    x5=y1+y2;
}

Or I can reorder the declaration of data members in class body like this:

class MyClass{
public:
    MyClass();
    int x1;
    int x2;
    int x3;
    int x4;
private:
    int y1;
    int y2;
public:
    int x5;
};

But here I'm declaring a scope of public members unnecessarily twice!

How to fix (not get rid) of these warnings and still use member-initializer list for initialization?

As you can see the data members in the first original form are defined in a correct order according to their usages, but the compiler still can't figure out that itself.

Bobo Feugo
  • 162
  • 1
  • 10
  • I don't think you can, because in member-initialization the variables must be in the order they are initializated. However, there is a more important question. Why do you put 5 `int` variables as public? It breaks most of encapsulation. – Gary Strivin' Mar 29 '21 at 12:58
  • If your actual class uses ints, then why not go with your first solution (set members in body)? Using MIL for ints doesn't really achieve much (unless the members are say, const). You can even have x1..x4, y1, y2 in the MIL and set x5 in the body. – TrebledJ Mar 29 '21 at 12:59
  • 1
    why is the last option not fine? There is nothing wrong with sections of `private` and `public` members alternating if thats what you need – 463035818_is_not_an_ai Mar 29 '21 at 13:23

2 Answers2

2

As you can see the data members in the first original form are defined in a correct order according to their usages,

On the contrary, we can see the opposite: In the first example, the members are declared in an incorrect order according to their usages:

    int x5;

private:
    int y1;
    int y2;

As you can see, x5 is declared before y1 and y2. Therefore x5 is initialised before the other two.

y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4)), x5(y1+y2)

Here, you've misleadingly ordered the member initialiser list in a different order than the members are initialised. -Wreorder warning is consequence of this choice.

Furthermore, the initialiser uses the values of y1 and y2 which aren't initialised yet. -Wuninitialized warning is consequence of that.


But here I'm declaring a scope of public members unnecessarily twice!

This is hardly a problem.

How to fix (not get rid) of these warnings and still use member-initializer list for initialization?

You've already shown two solutions, one of which satisfies your desire to use member initialiser list. I recommend the solution that satisfies all your desired requirements.

If you prefer to not change the order of the members, then the first solution can be adjusted to still use member initialiser list for all other members, except the one that depends on latter members:

MyClass::MyClass(): 
    x1(1), x2(2), x3(3), x4(4), x5{}
    y1(someFunc1(x1, x2)), y2(someFunc2(x3, x4))
{
    x5 = y1 + y2;
}

Complex initialisation like this is the purpose for which the constructor body exists.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thanks for the feedback! As you said: `the members are declared in an incorrect order according to their usages` What I tried to demonstrate is that if the compiler is capable to spot the mismatching between declarations and initializations, then why it cannot similarly find the matching between initializations and usages? I kinda think the compiler should do more here! I always hear compilers are very smart and can do a lot for you, and then find such shortfalls! – Bobo Feugo Mar 30 '21 at 09:57
  • @BoboFeugo: compiler cannot "fix" the order for you you might have several constructor with conflicting ordering, but you have only one destruction which should use the "correct" order. – Jarod42 Mar 30 '21 at 10:33
1

You might use delegating constructors:

class MyClass{

public:
    MyClass() : MyClass(1, 2, 3, 4) {}

//private:

    MyClass(int x1, int x2, int x3, int x4) :
        MyClass(x1, x2, x3, x4, someFunc1(x1, x2), someFunc2(x3, x4))
    {}

    MyClass(int x1, int x2, int x3, int x4, int y1, int y2) :
        x1(x1), x2(x2), x3(x3), x4(x4), x5(y1 + y2), y1(y1), y2(y2)
    {}
public:
    int x1;
    int x2;
    int x3;
    int x4;
    int x5;

private:
    int y1;
    int y2;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • While you made it look even more complicated, you still managed to get it to work with member-initializer list without changing the order of declarations! Hat off. – Bobo Feugo Mar 30 '21 at 09:57