MikeT MikeT - 3 months ago 10
C++ Question

Whiyam I getting this unexpected behaviour constructing class objects?

I created a class named result_line and have been having problems with it's constructor. That is that it wasn't being assigned the expected values.
I have since created a similar, but more frugal, class named rsltline and this appears to work.

Here's the 2 classes :-

result_line

class result_line {
private:
HWND rwnd;
int result_flags;
int result_extraflags;
public:
result_line(HWND, int, int);
~result_line();
HWND result_lineGetHWND();
void result_lineSetHWND(HWND);
int result_lineGetFlags();
int result_lineGetExtraFlags();
DINT result_lineGetBothFlags();
void result_lineSetFlags(int);
void result_lineSetExtraFlags(int);
void result_lineSetBothFlags(int,int);
void result_lineSetBothFlags(DINT);
};
// Constructor for result_line(HWND) and result_line(HWND, result_flag)
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags) {
rwnd = rwnd;
result_flags = 30;
result_extraflags = 40;
}
result_line::~result_line() {}
HWND result_line::result_lineGetHWND() { return rwnd; }
int result_line::result_lineGetFlags() { return result_flags; }
int result_line::result_lineGetExtraFlags() { return result_extraflags; }
DINT result_line::result_lineGetBothFlags() { return DINT(result_flags,result_extraflags); }
void result_line::result_lineSetHWND(HWND rwnd) { rwnd = rwnd; }
void result_line::result_lineSetFlags(int result_flags) { result_flags = result_flags; }
void result_line::result_lineSetExtraFlags(int result_extraflags) { result_extraflags = result_extraflags; }
void result_line::result_lineSetBothFlags(int result_flags, int result_extraflags) {
result_flags = result_flags;
result_extraflags = result_extraflags;
}
void result_line::result_lineSetBothFlags(DINT dint) {
result_flags = dint.aint;
result_extraflags = dint.bint;
}


rsltline

class rsltline {
private:
HWND rlHWND;
int rlflag1;
int rlflag2;
public:
rsltline(HWND, int, int);
HWND rsltlineGetHWND();
int rsltlineGetFlag1();
int rsltlineGetFlag2();
};
rsltline::rsltline(HWND hwnd, int rf1, int rf2) {
rlHWND = hwnd;
rlflag1 = rf1;
rlflag2 = rf2;
}
HWND rsltline::rsltlineGetHWND() { return rlHWND; }
int rsltline::rsltlineGetFlag1() { return rlflag1; }
int rsltline::rsltlineGetFlag2() { return rlflag2; }


I have the following code to create and then display instances using the two classes (the last using the rsltline class as opposed to the result_line class, as used by the first two) :-

result_line foo = result_line(0,3,6);
std::cout << "HWND=" << foo.result_lineGetHWND() <<
"\tFLAGS=" << foo.result_lineGetFlags() <<
"\tEXTRAFLAGS=" << foo.result_lineGetExtraFlags() <<
std::endl;
result_line testrslt = result_line((HWND) 0,100,200);
std::cout << "HWND=" << testrslt.result_lineGetHWND() <<
"\tFLAGS=" << testrslt.result_lineGetFlags() <<
"\tEXTRAFLAGS=" << testrslt.result_lineGetExtraFlags() <<
std::endl;
rsltline myrsltline = rsltline((HWND)2,4,6);
std::cout << "HWND=" << myrsltline.rsltlineGetHWND() <<
"\tFLAGS=" << myrsltline.rsltlineGetFlag1() <<
"\tEXTRAFLAGS=" << myrsltline.rsltlineGetFlag2() <<
std::endl;


The first two return Unexpected Results, the last using the rsltline class works as expected. The results are:-


HWND=0 FLAGS=0 EXTRAFLAGS=0

HWND=0 FLAGS=1997196755 EXTRAFLAGS=0

HWND=0x2 FLAGS=4 EXTRAFLAGS=6

Process returned 0 (0x0) execution time : 35.007 s Press any key to
continue.


The only thing that I can think that may be causing this is the naming of the former. Although, perhaps it's simply a case of me needing to visit an optician :).

Answer

Lets take a closer look at the result_line constructor:

// Constructor for result_line(HWND) and result_line(HWND, result_flag)
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags) {
    rwnd = rwnd;
    result_flags = 30;
    result_extraflags = 40;
}

You declare a set of arguments, named rwnd, result_flags and result_extraflags. These are the same a local variables inside the constructor function body, and therefore shadows the member variables with the same name.

What happens is that you assign values to the local variables (the arguments), and not the member variables.

There are three solutions: Either use different names for the arguments, or prefix the member variables with this->, or use a constructor initializer list:

result_line::result_line(HWND rwnd, int result_flags, int result_extraflags)
    : rwnd{rwnd}, result_flags{30], result_extraflags{40}
{
    // Empty body
}