45

My understanding of constructor chaining is that , when there are more than one constructors in a class (overloaded constructors) , if one of them tries to call another constructor,then this process is called CONSTRUCTOR CHAINING , which is not supported in C++ . Recently I came across this paragraph while reading online material.... It goes like this ...

You may find yourself in the situation where you want to write a member function to re-initialize a class back to default values. Because you probably already have a constructor that does this, you may be tempted to try to call the constructor from your member function. As mentioned, chaining constructor calls are illegal in C++. You could copy the code from the constructor in your function, which would work, but lead to duplicate code. The best solution in this case is to move the code from the constructor to your new function, and have the constructor call your function to do the work of initializing the data.

Does a member function calling the constructor also come under constructor chaining ?? Please throw some light on this topic in C++ .

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
progammer
  • 1,951
  • 11
  • 28
  • 50
  • 3
    I'd say not, and it's a non-sequitur for the article to say that constructor chaining is illegal, immediately after saying that some arbitrary member function (not necessarily a constructor) might think it wants to call a constructor to reset the value. But who knows, you haven't cited the article or quoted where it describes constructor chaining, so maybe it's using it in some unusual sense already described elsewhere. – Steve Jessop Sep 08 '11 at 13:57
  • 1
    It's not illegal. Calling a constructor from a member has the effect of creating a temporary object to which the construction applies, not the 'this' object from which you make the call. – Amardeep AC9MF Sep 08 '11 at 13:59
  • 1
    @Amardeep: agreed, it would be more accurate to say that constructor chaining is "impossible" in C++03, rather than "illegal". There's simply no syntax to describe doing it. As you say, by the normal definition calling a constructor isn't at all the same thing as constructor chaining. – Steve Jessop Sep 08 '11 at 14:00
  • @ Steve .. and everyone else intrested .. Here's the [link](http://www.learncpp.com/cpp-tutorial/88-constructors-part-ii/) :) – progammer Sep 08 '11 at 14:09
  • 13
    C++ constructor call another constructor is a feature in c++ 11, called Delegating Constructors, see link http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf – RoundPi Sep 08 '11 at 14:25

5 Answers5

43

C++11 allows constructor chaining (partially). This feature is called "delegating constructors". So in C++11 you can do the following

class Foo
{
public:
    Foo(int a) : Foo() { _a = a; }
    Foo(char* b) : Foo() { _b = b; }
    Foo() { _c = 1.5; }
private:
    int _a = 0;
    char* _b = nullptr;
    double _c;
};

However, there is a severe limitation that a constructor that calls another constructor is not allowed to initialize any other members. So you cannot do the following with a delegating constructor:

class Foo
{
public:
    Foo(int a) : Foo(), _a(a) { }
    Foo(char* b) : Foo(), _b(b) { }
    Foo() { _c = 1.5; }
private:
    int _a = 0;
    char* _b = nullptr;
    double _c;
};

MSVC++2013 gives compile error "C3511: a call to a delegating constructor shall be the only member-initializer" for the latter code example.

Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158
  • I guess that makes sense. Calling the default constructor should initialize all fields, so initializing them again could be very bad. – lmat - Reinstate Monica Mar 20 '18 at 12:59
  • If you feel you need to do this, it suggests that there's a small parent class trying to get out of `Foo`. In this case, `FooParent` would have the member `c`, and `FooChild` would inherit from it and add `a` and `b`. – quant_dev Aug 16 '19 at 20:16
22

The paragraph basically says this:

class X
{
   void Init(params) {/*common initing code here*/ }
   X(params1) { Init(someParams); /*custom code*/ } 
   X(params2) { Init(someOtherParams); /*custom code*/ } 
};

You cannot call a constructor from a member function either. It may seem to you that you've done it, but that's an illusion:

class X
{
public:
    X(int i):i(i){}
    void f()
    {
       X(3); //this just creates a temprorary - doesn't call the ctor on this instance
    }
    int i;
};

int main()
{
    using std::cout;
    X x(4);
    cout << x.i << "\n"; //prints 4
    x.f();
    cout << x.i << "\n"; //prints 4 again
}
Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • @ Armen .. You mean the first time it is printing a 4 , it is actually calling the constructor , and second time when it prints 4 , though I feel as if I have acheived the result by calling the constructor( from the function void f() ), what EXACTLY is happening is not that .. !!! Is it ?? But I didn't understand your first comment in the above code // this just creates a temporary - doesn't call the ctor on this instance . Could you explain it to me a bit more clearly ? – progammer Sep 08 '11 at 14:21
4

That's not what the text says. It's suggesting your constructor call a member function which is normal and legal. This is to avoid explicitly calling the ctor again and to avoid duplicating code between your ctor and reset function.

Foo::Foo() {
  Init();
}

void Foo::Reset() {
  Init();
}

void Foo::Init() {
  // ... do stuff ...
}
i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
  • It's true that the text is not recommending that the function call the constructor, however the text says "you may be tempted to try to call the constructor from your member function. As mentioned, chaining constructor calls are illegal in C++". This suggests that via some confusion of ideas, the author thought that "chaining constructor calls" has something to do with "calling the constructor from your member function", regardless of whether the article is recommending doing it or not. Could just be dodgy editing, of course. – Steve Jessop Sep 08 '11 at 14:02
  • "Because you probably already have a constructor that does this, you may be tempted to try to call the constructor from your member function." I thought this meant that A MEMBER FUNCTION CALLING A CONSTRUCTOR should be avoided .. !!??? – progammer Sep 08 '11 at 14:03
  • @Appy: not necessarily. For example, in a class called `Foo` `*this = Foo();` might be a perfectly reasonable way to reset the object, if not necessarily the most efficient. Then the function calls the constructor, it just doesn't call it to construct `this`. – Steve Jessop Sep 08 '11 at 14:04
  • @ Steve ... Thanks for the help .. :) I guess it IS just some kinda dodgy editing .. – progammer Sep 08 '11 at 14:05
0

I'm not sure if it (calling a constructor from a member function) will work or not, but it's a bad practice. moving the initialize code to a new function is the logic way.

Basically saying, Don't call the constructor unless you constructing...

Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94
  • I agree with Johnsyweb. Calling a constructor from another will just create a temporary local variable inside it and delete it once the constructor exits. The `this` object is not affected by any of that. The only way to do it is a placement new and the C++ FAQ repeated lots of times that it's a horrible thing to do. – MasterMastic Apr 21 '13 at 08:45
-2

when we call constructor from a member function, then it will temporary create a object of its type. in case if we are calling in derived class function then all the parent constructors are also gets executed and destroyed using destructor once function goes out of scope.

its not a Good Practice to call the constructors in member functions since it creates objects of every class derived.

Narayan
  • 48
  • 2