By Stormenet


2008-11-21 09:43:08 8 Comments

As a C# developer I'm used to run through constructors:

class Test {
    public Test() {
        DoSomething();
    }

    public Test(int count) : this() {
        DoSomethingWithCount(count);
    }

    public Test(int count, string name) : this(count) {
        DoSomethingWithName(name);
    }
}

Is there a way to do this in C++?

I tried calling the Class name and using the 'this' keyword, but both fails.

15 comments

@user8683714 2017-10-28 11:53:30

Simply put, you cannot before C++11.

C++11 introduces delegating constructors:

Delegating constructor

If the name of the class itself appears as class-or-identifier in the member initializer list, then the list must consist of that one member initializer only; such constructor is known as the delegating constructor, and the constructor selected by the only member of the initializer list is the target constructor

In this case, the target constructor is selected by overload resolution and executed first, then the control returns to the delegating constructor and its body is executed.

Delegating constructors cannot be recursive.

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};

Note that a delegating constructor is an all-or-nothing proposal; if a constructor delegates to another constructor, the calling constructor isn't allowed to have any other members in its initialization list. This makes sense if you think about initializing const/reference members once, and only once.

@kchoose2 2008-11-22 06:36:13

It is worth pointing out that you can call the constructor of a parent class in your constructor e.g.:

class A { /* ... */ };

class B : public A
{
    B() : A()
    {
        // ...
    }
};

But, no, you can't call another constructor of the same class.

@JohnIdol 2008-11-21 10:04:17

C++11: Yes!

C++11 and onwards has this same feature (called delegating constructors).

The syntax is slightly different from C#:

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {}
};

C++03: No

Unfortunately, there's no way to do this in C++03, but there are two ways of simulating this:

  1. You can combine two (or more) constructors via default parameters:

    class Foo {
    public:
      Foo(char x, int y=0);  // combines two constructors (char) and (char, int)
      // ...
    };
    
  2. Use an init method to share common code:

    class Foo {
    public:
      Foo(char x);
      Foo(char x, int y);
      // ...
    private:
      void init(char x, int y);
    };
    
    Foo::Foo(char x)
    {
      init(x, int(x) + 7);
      // ...
    }
    
    Foo::Foo(char x, int y)
    {
      init(x, y);
      // ...
    }
    
    void Foo::init(char x, int y)
    {
      // ...
    }
    

See the C++FAQ entry for reference.

@bobobobo 2010-02-18 22:53:43

Actually remarkably default parameters makes for a very clean way to do what we'd commonly accomplish calling this() in C#

@greydet 2013-07-24 15:09:19

Note that the proposed solution not using C++11 only works if the class to construct does not have inheritance nor constant fields. I did not found a way to initialize parent class and constant fields outside of the initialization list.

@sud03r 2013-08-08 08:23:31

Thanks for your answer. One important point to note is that such a code will compile and run. One of the answers below highlights this point. It will be great if you could link the answer below as well, because most people see the top answer only.

@Eugene Ryabtsev 2014-04-08 10:31:50

@bobobobo Using default parameters compiles them into the caller, so that's not very clean. Overloading is more code, correct, but the implementation encapsulates the defaults.

@locka 2014-09-12 10:45:21

The one downside of using init() is you can't declare a pointer or ref that is const (as in the ref/pointer is const rather the thing it points at) if you don't initialise it in the constructor().

@raidsan 2014-12-06 15:03:08

"Delegating constructors"---Visual Studio 2013 supports this Features, see: msdn.microsoft.com/en-us/library/hh567368.aspx

@PC Luddite 2015-08-11 08:04:45

@bobobobo C# supports default parameters in VS2010 (C# 4.0). See here: msdn.microsoft.com/en-us/library/dd264739.aspx

@gen 2016-07-08 08:17:36

@JohnIdol how about writing: Foo:Foo(char x) { Foo(x, int(x)+7); } What would this do?

@Tristan 2016-09-21 21:09:36

What is the execution order?

@Phil1970 2017-01-28 15:02:46

@gen It won't work as desired for sure (if it ever compile).

@Guy Avraham 2017-08-12 14:28:27

Does calling the argument Ctor from the copy Ctor (in C++11) considered as "good practice" OR should one avoid this ?

@Jim Balter 2017-09-13 18:59:08

@gen (aside from the missing second colon) It will create a temporary Foo and then immediately discard it.

@Samuel 2017-11-21 07:45:18

I am falling for this every time. IDE is 2017, retargeted compiler is 2012 which is not able to do this, gosh.

@Jamie S 2018-04-01 01:27:36

@locka There's a hacky way around this, using the comma operator which allows you to call an init() function in the initializer list. It does, unfortunately, require another member to be initialized separately from the initializer list, which may not be desired.

@val 2018-04-30 21:33:12

Where should I place C++11 solution? In .hpp or .cpp?

@srm 2018-06-18 19:00:30

@val in the .cpp. It's part of the implementation details of the function, so it is not part of the declaration signature.

@Galaxy 2018-08-19 20:29:50

There are 2^10 up votes!

@ohlemacher 2009-08-12 15:31:52

I believe you can call a constructor from a constructor. It will compile and run. I recently saw someone do this and it ran on both Windows and Linux.

It just doesn't do what you want. The inner constructor will construct a temporary local object which gets deleted once the outer constructor returns. They would have to be different constructors as well or you would create a recursive call.

Ref: https://isocpp.org/wiki/faq/ctors#init-methods

@ChiefTwoPencils 2013-10-28 08:05:36

Good point; most just said "no you can't". I can :). I did this switching back and was using the original ctor to decide which other to call. In debug the object could be seen in the second, everything gets initialized but goes back to default values when returned. Makes a lot of sense when you think about it.

@Lightness Races in Orbit 2014-11-26 23:38:40

This is not "calling a constructor". The only place you can "call a constructor" directly is in the ctor-initializer in C++11. What you're doing in this example is constructing an object, which is a different kettle of fish. Don't be misled by the fact that it looks like a function call to the constructor, because it's not one! There is in fact no way to make a function call to the constructor, which is why it is impossible to construct an instance of a class whose only constructor(s) are instantiations of a function template whose template arguments cannot be deduced.

@Lightness Races in Orbit 2014-11-26 23:40:04

(That is, it is syntactically impossible to explicitly provide template arguments to a constructor.)

@celticminstrel 2015-06-23 02:23:30

There is actually one way to make a function call to a constructor - using placement new syntax. This usually isn't what you want, though. (And it doesn't do anything to allow you to explicitly provide template arguments.)

@Leon 2015-09-23 15:17:25

using placement new would still create a new object, albeit at the same memory location. But a different object nevertheless, and it is possible to put together the code that proves this.

@gyula 2016-09-09 10:38:09

Would be more easy to test, than decide :) Try this:

#include <iostream>

class A {
public:
    A( int a) : m_a(a) {
        std::cout << "A::Ctor" << std::endl;    
    }
    ~A() {
        std::cout << "A::dtor" << std::endl;    
    }
public:
    int m_a;
};

class B : public A {
public:
    B( int a, int b) : m_b(b), A(a) {}
public:
    int m_b;
};

int main() {
    B b(9, 6);
    std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl;    
    return 0;
}

and compile it with 98 std: g++ main.cpp -std=c++98 -o test_1

you will see:

A::Ctor
Test constructor delegation a = 9; b = 6
A::dtor

so :)

@Actarus 2017-10-03 07:03:54

This was not the initial question, he is not asking about calling a base class constructor, but another constructor in the same class.

@V15I0N 2015-11-10 21:18:53

This approach may work for some kinds of classes (when the assignment operator behaves 'well'):

Foo::Foo()
{
    // do what every Foo is needing
    ...
}

Foo::Foo(char x)
{
    *this = Foo();

    // do the special things for a Foo with char
    ...
}

@lyngvi 2011-03-24 16:53:45

If you want to be evil, you can use the in-place "new" operator:

class Foo() {
    Foo() { /* default constructor deliciousness */ }
    Foo(Bar myParam) {
      new (this) Foo();
      /* bar your param all night long */
    } 
};

Seems to work for me.

edit

As @ElvedinHamzagic points out, if Foo contained an object which allocated memory, that object might not be freed. This complicates things further.

A more general example:

class Foo() {
private:
  std::vector<int> Stuff;
public:
    Foo()
      : Stuff(42)
    {
      /* default constructor deliciousness */
    }

    Foo(Bar myParam)
    {
      this->~Foo();
      new (this) Foo();
      /* bar your param all night long */
    } 
};

Looks a bit less elegant, for sure. @JohnIdol's solution is much better.

@Stormenet 2011-03-24 20:05:25

Its seems it is not something advised to do as you can read at the end of 10.3 parashift.com/c++-faq-lite/ctors.html#faq-10.3

@Deadcode 2012-11-12 10:45:04

It seems to me the only downside of this is that it adds a little overhead; new(this) tests if this==NULL and skips the constructor if it does.

@Lightness Races in Orbit 2014-11-26 23:42:07

This is almost certainly UB.

@holgac 2015-01-13 01:46:19

Doesn't this theoretically call constructors of fields more than once? Compilers might be fixing it but you can't really trust that. Besides, although not a great idea, I might have some class members in Foo that change static/global variables in their constructor, so I would expect them to do that operation twice with that code.

@Elvedin Hamzagic 2015-06-10 10:21:39

This is really evil. Suppose that you're allocating memory in that constructor, and deallocating it in destructor. No memory will be freed.

@Elvedin Hamzagic 2015-06-10 11:21:54

But you can still escape from disaster if you call the destructor explicitly: this->~Foo();, before new (this) Foo();

@lyngvi 2015-06-10 11:46:35

@ElvedinHamzagic: Good point (holgac got this as well); updated post.

@lyngvi 2015-06-10 11:46:46

@Stormenet: good to know. Broken link though (403)?

@Stormenet 2015-06-10 13:34:18

@lyngvi can't edit my previous comment... Anyhow, this is the new location it seems: isocpp.org/wiki/faq/dtors#placement-new

@Ben Voigt 2018-03-18 17:35:03

Be aware of the restrictions on replacing an object like this -- you cannot have any non-static data members which are const or references.

@Pantelis Sopasakis 2014-11-02 00:19:49

I would propose the use of a private friend method which implements the application logic of the constructor and is the called by the various constructors. Here is an example:

Assume we have a class called StreamArrayReader with some private fields:

private:
    istream * in;
      // More private fields

And we want to define the two constructors:

public:
    StreamArrayReader(istream * in_stream);
    StreamArrayReader(char * filepath);
    // More constructors...

Where the second one simply makes use of the first one (and of course we don't want to duplicate the implementation of the former). Ideally, one would like to do something like:

StreamArrayReader::StreamArrayReader(istream * in_stream){
    // Implementation
}

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    StreamArrayReader(&instream);
    instream.close();
}

However, this is not allowed in C++. For that reason, we may define a private friend method as follows which implements what the first constructor is supposed to do:

private:
  friend void init_stream_array_reader(StreamArrayReader *o, istream * is);

Now this method (because it's a friend) has access to the private fields of o. Then, the first constructor becomes:

StreamArrayReader::StreamArrayReader(istream * is) {
    init_stream_array_reader(this, is);
}

Note that this does not create multiple copies for the newly created copies. The second one becomes:

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    init_stream_array_reader(this, &instream);
    instream.close();
}

That is, instead of having one constructor calling another, both call a private friend!

@pqnet 2017-10-21 20:27:30

It seems to me that using a friend method has no advantage over a normal private method. Why would you do that?

@XPD 2014-01-06 10:52:33

When calling a constructor it actually allocates memory, either from the stack or from the heap. So calling a constructor in another constructor creates a local copy. So we are modifying another object, not the one we are focusing on.

@Lightness Races in Orbit 2014-11-26 23:46:19

You cannot "call a constructor"; please see my comments on ohlemacher's answer. However you are, essentially, correct.

@Elvedin Hamzagic 2015-06-10 09:53:40

Constructor is just an initializer, so creating common initializer outside a constructor is an old-fassion method. Memory is allocated before the constructor is ever called, commonly when operator new is called or malloc...

@Ben L 2011-09-22 20:07:00

In C++11, a constructor can call another constructor overload:

class Foo  {
     int d;         
public:
    Foo  (int i) : d(i) {}
    Foo  () : Foo(42) {} //New to C++11
};

Additionally, members can be initialized like this as well.

class Foo  {
     int d = 5;         
public:
    Foo  (int i) : d(i) {}
};

This should eliminate the need to create the initialization helper method. And it is still recommended not calling any virtual functions in the constructors or destructors to avoid using any members that might not be initialized.

@izogfif 2012-02-20 10:00:51

In Visual C++ you can also use this notation inside constructor: this->Classname::Classname(parameters of another constructor). See an example below:

class Vertex
{
 private:
  int x, y;
 public:
  Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
  Vertex()
  {
   this->Vertex::Vertex(-1, -1);
  }
};

I don't know whether it works somewhere else, I only tested it in Visual C++ 2003 and 2008. You may also call several constructors this way, I suppose, just like in Java and C#.

P.S.: Frankly, I was surprised that this was not mentioned earlier.

@Kevin 2012-08-10 13:59:48

I tried this on g++ under Ubuntu (4.4.3). It didn't work: In constructor ‘Vertex::Vertex()’: error: invalid use of ‘class Vertex’.

@izogfif 2012-10-31 15:29:26

I tested it under Visual Studio 2003 .NET Architect edition - works fine.

@Alexander Drichel 2013-06-11 13:59:15

This method is very dangerous! It produce memory leak if members are not from a POD-Type. For example std::string.

@Lightness Races in Orbit 2014-11-26 23:40:51

Frankly, I'm astounded and disappointed that Visual C++ allows this. It's very broken. Let's not persuade people to use this strategy.

@pqnet 2017-10-21 20:24:15

is this similar to placement new?

@Ben Voigt 2018-03-18 17:37:04

@LightnessRacesinOrbit: It seems that it should create a temporary object, same as Vertex(-1, -1). The only difference is use of qualified lookup instead of unqualified, but it still names the same class.

@Lightness Races in Orbit 2018-03-18 18:48:49

@BenVoigt: What's with the this-> though?

@Ben Voigt 2018-03-18 18:53:39

@LightnessRacesinOrbit: C++ allows looking up static class members using member access syntax (as an alternative to the usual classname+scope operator). Can't remember whether that applies to nested types and typedefs as well. The "injected class-name" rule means that the class's name can be found as if it were a member name.

@Lightness Races in Orbit 2018-03-18 18:54:20

@BenVoigt: The constructor is not a static class member; it is a "special member function". This syntax is utter nonsense.

@Ben Voigt 2018-03-18 18:54:58

@LightnessRacesinOrbit: What's named is not the constructor (it has no name), but the type itself. Via injected class name.

@Lightness Races in Orbit 2018-03-18 18:55:34

@BenVoigt: Then we're back to this-> making no sense. This is not valid C++, period.

@Ben Voigt 2018-03-18 18:55:57

However, I think nested types can't be found via member access, or else I would have been writing c.iterator it = c.begin() instead of std::vector<Blah>::iterator it = c.begin();

@Lightness Races in Orbit 2018-03-18 18:56:23

@BenVoigt: Yes, exactly.

@Ben Voigt 2018-03-18 19:00:30

Which is sad, because this->typename T varname; would be very convenient for accessing a dependent name in CRTP.

@e.James 2011-11-25 00:54:11

Another option that has not been shown yet is to split your class into two, wrapping a lightweight interface class around your original class in order to achieve the effect you are looking for:

class Test_Base {
    public Test_Base() {
        DoSomething();
    }
};

class Test : public Test_Base {
    public Test() : Test_Base() {
    }

    public Test(int count) : Test_Base() {
        DoSomethingWithCount(count);
    }
};

This could get messy if you have many constructors that must call their "next level up" counterpart, but for a handful of constructors, it should be workable.

@Cyrille Ka 2008-11-21 10:00:12

No, you can't call one constructor from another in C++03 (called a delegating constructor).

This changed in C++11 (aka C++0x), which added support for the following syntax:
(example taken from Wikipedia)

class SomeType
{
  int number;

public:
  SomeType(int newNumber) : number(newNumber) {}
  SomeType() : SomeType(42) {}
};

@Tomáš Zato 2015-09-14 13:52:27

But how is that different from standard default parameter syntax?

@Cyrille Ka 2015-09-14 18:14:10

@TomášZato One thing that you can't do with default parameters is using your parameter to call the other constructor: SomeType(string const &s) { /*...*/ } SomeType(char const *pc) : SomeType(string(pc)) { /*...*/ }

@Kaiserludi 2016-01-22 17:00:23

@TomášZato Another difference is that with default parameters you have just one constructor that you have to make either public, protected or private, while with 2 constructors, one calling the other, you can restrict access to one of them without having to also restrict access to the other one.

@Kaiserludi 2016-01-22 17:22:35

PS: of course you could also do that with a private init function that gets called by multiple constructors, but that would not work for initialization lists.

@Rptx 2016-03-19 22:59:00

It's also different from default values because you can change it without recompiling the code that uses the library. With default values, those values are "baked" into the call.

@unwind 2008-11-21 09:56:18

No, in C++ you cannot call a constructor from a constructor. What you can do, as warren pointed out, is:

  • Overload the constructor, using different signatures
  • Use default values on arguments, to make a "simpler" version available

Note that in the first case, you cannot reduce code duplication by calling one constructor from another. You can of course have a separate, private/protected, method that does all the initialization, and let the constructor mainly deal with argument handling.

@warren 2008-11-21 09:49:40

If I understand your question correctly, you're asking if you can call multiple constructors in C++?

If that's what you're looking for, then no - that is not possible.

You certainly can have multiple constructors, each with unique argument signatures, and then call the one you want when you instantiate a new object.

You can even have one constructor with defaulted arguments on the end.

But you may not have multiple constructors, and then call each of them separately.

@Jonathan 2008-11-21 09:50:31

He's asking if one constructor can call another one. Java and C# allow this.

@warren 2008-11-21 11:30:48

right - that's not possible in C++

Related Questions

Sponsored Content

20 Answered Questions

[SOLVED] How do I call one constructor from another in Java?

  • 2008-11-12 20:10:19
  • ashokgelal
  • 766064 View
  • 2060 Score
  • 20 Answer
  • Tags:   java constructor

14 Answered Questions

[SOLVED] How can I profile C++ code running on Linux?

  • 2008-12-17 20:29:24
  • Gabriel Isenberg
  • 466974 View
  • 1648 Score
  • 14 Answer
  • Tags:   c++ unix profiling

24 Answered Questions

[SOLVED] Image Processing: Algorithm Improvement for 'Coca-Cola Can' Recognition

31 Answered Questions

[SOLVED] How do I detect unsigned integer multiply overflow?

10 Answered Questions

[SOLVED] Calling the base constructor in C#

10 Answered Questions

8 Answered Questions

[SOLVED] Call one constructor from another

  • 2010-10-24 16:06:31
  • Avi
  • 406147 View
  • 876 Score
  • 8 Answer
  • Tags:   c# constructor

10 Answered Questions

[SOLVED] Throwing exceptions from constructors

17 Answered Questions

[SOLVED] Virtual member call in a constructor

9 Answered Questions

[SOLVED] What are the rules for calling the superclass constructor?

Sponsored Content