abhimanyuaryan
abhimanyuaryan

Reputation: 4024

re-initialise using delegating constructor

I have this class X, using delegating constructor I want to change only the value i and j as 0. Is it possible to do so?

class X{
public:
    X() = default; 
    X(int ival, int jval) : i{ ival }, j{ jval } {} 
    X(int new_i) : i{ new_i }, X(i, 0) {}    //error here


private:
    int i; 
    int j; 
};

int main()
{
    X x{ 345, 54 };

    x = X{ 34 };  //annoymous copy changes only the i:member
    return 0; 
}

EDIT: I know X(int new_int) : X{new_int, 0} will work but i wanted to know what's the error if initialise one more variable in the list.

May be I have another z and I want to initialise that along with i and j.

i.e. X(int new_i) :z{ new_i }, X(new_i, 0) {}

Upvotes: 2

Views: 83

Answers (3)

Walter
Walter

Reputation: 45444

You cannot have a delegating constructor and another member-initialiser in the initialiser list. That's not allowed, because the order of initialisation cannot possibly be the order of member declaration, instead some variables will be initialised twice, which is potentially ill-defined.

If your example were allowed, then the constructor in question would first initialise i<-new_i, then i<--i, then j<--0. With non-const int, this may be feasable, but not with more general types.


Simply initialise the objects via the delegation:

class X
{
public:
  X() = default; 
  X(int ival, int jval) : i{ival}, j{jval} {} 
  X(int ival) : X(ival, 0) {}    
private:
  int i; 
  int j; 
};

Though in this case, it's better to use default arguments:

class X
{
public:
  X() = default; 
  X(int ival, int jval=0) : i{ival}, j{jval} {} 
private:
  int i; 
  int j; 
};

You should also consider to use the explicit keyword for single-argument constructors to avoid unpleasant surprises ... as in

void foo(X);
foo(1);       // calls foo(X(1));

Upvotes: 1

R Sahu
R Sahu

Reputation: 206607

Just use

X(int new_i) :  X(new_i, 0) {}

From the C++ Draft Standard N3337 (emphasis mine):

12.6.2 Initializing bases and members

6 A mem-initializer-list can delegate to another constructor of the constructor’s class using any class-or-decltype that denotes the constructor’s class itself. If a mem-initializer-id designates the constructor’s class, it shall be the only mem-initializer;

Upvotes: 2

vsoftco
vsoftco

Reputation: 56557

Why don't you do this?

X(int new_i) :X(new_i, 0){...}

In this way, you will set j-th value to 0, and have only x variable.

Upvotes: 1

Related Questions