Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a C++ class Constructor from another Constructor [duplicate]

I'm trying to create an object in C++ that requires multiple object constructors. Say Foo() and Foo(int) where Foo(int) then calls Foo(). The simplified code is written below:

#include <iostream>
class Foo{

private:
        int iX; 

public:
        void printX(string sLabel){
            cout << sLabel << " : " << " Foo::iX = " << Foo::iX << endl;
        };  
        void setX(int iX){
            Foo::iX = iX; 
            Foo::printX("setX(void) Method");
        };  
        Foo(){
            Foo::iX = 1;
            Foo::printX("Foo(void) Constructor");
        };
        Foo(int iX){
            Foo::setX(iX);
            Foo::printX("Foo(int) Constructor");
            Foo::Foo();
            Foo::printX("Foo(int) Constructor");

        };  
};

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

    Foo bar(2);

    return 0;
}

The output of which is

setX(void) Method :  Foo::iX = 2
Foo(int) Constructor :  Foo::iX = 2
Foo(void) Constructor :  Foo::iX = 1
Foo(int) Constructor :  Foo::iX = 2

As the results indicate setX method works as expected. Foo::iX is equal to 2 inside and outside of scope of that function.

However when calling the Foo(void) constructor from within the Foo(int) constructor, Foo::iX stays equal to 1 only within that constructor. As soon as it exits out that method, it reverts back to 2.

So my question is 2-fold:

  1. Why does C++ behave this (a constructor cannot be called from within another constructor without values that were assigned)?
  2. How can you create multiple constructor signatures, but without redundant duplicate code doing the same thing?
like image 967
WoodMath Avatar asked Aug 29 '16 05:08

WoodMath


2 Answers

Foo::Foo(); in Foo::Foo(int) is not invoking the default constructor on the current object as you expected. It just constructs a temporary Foo, which has nothing to with the current object.

You can use delegating constructor (since C++11) like this:

Foo(int iX) : Foo() {
    // ...
}; 

Note that Foo::Foo() will be invoked in advance of the body of Foo::Foo(int) here.

An alternative to avoid duplicated code is to use setX() as a common initialization method. (Or make a new one if not appropriate.)

Foo() {
    setX(1);
    // ...
};
Foo(int iX) {
    setX(iX);
    // ...
}; 
like image 125
songyuanyao Avatar answered Nov 15 '22 17:11

songyuanyao


If you are able to use a C++11 compiler, you can use delegating constructors.

// Use Foo(int) to initialize the object when default constructor is used.
Foo() : Foo(1) {}
like image 43
R Sahu Avatar answered Nov 15 '22 17:11

R Sahu