views:

334

answers:

4
class A{
  A(int a = 5){
    DoSomething();
    A();
  }
  A(){...}
}

Can the first constructor call the second one?

+18  A: 

No.

Extract the common functionality into a separate function instead. I usually name this function construct().

The "so-called" second call would compile, but has a different meaning in C++: it would construct a new object, a temporary, which will then be instantly deleted at the end of the statement. So, no.

A destructor, however, can be called without a problem.

Pavel Radzivilovsky
+1 - and `construct()`is a good name.
peterchen
+1 - and you should add that it will be possible to call constructors from constructors in the same class in the next C++ version (C++0x). See http://www2.research.att.com/~bs/C++0xFAQ.html#delegating-ctor
Klaim
+4  A: 

Not before C++0x, no.

BUT, just out of academic interest I've come up with a really horrible way* to do it using a placement operator "new" (someone care to point out how portable this is?)

#include <new>
#include <iostream>

class A
{
public:
    A(int i, int j)
        : i_(i), j_(j) { }

    A(int i)
    { new (this) A(i, 13); }

    int i_,j_;
};

int
main() {
    A a1(10,11), a2(10);
    std::cout
        << a1.i_ << ", "
        << a1.j_ << std::endl
        << a2.i_ << ", "
        << a2.j_ << std::endl;
    return 0;
}

*Hell no, I don't write this in the production code.

Alex B
I think it's pretty portable; placement-new is in the ISO C++ standard."Other uses, however, include calling a constructor directly, something which the C++ language does not otherwise permit."From wikipedia: http://en.wikipedia.org/wiki/Placement_syntax
haavee
What happens if A derives from a class B ? B's constructor will be called, and then A, which will then call new A' (another A constructor), and overwrite everything already done by B, and then call B again, then A'. Conclusion: if B does something meaningful (i.e. allocating a resource), this will break code (i.e. provoke a resource leak).
paercebal
@paercebal yes, this also won't work if A is an abstract class.
Alex B
+3  A: 

The answer is in fact "yes", but as others have suggested, it doesn't do what you want. You can of course use the constructor of a base class, either implicitly or explicitly:

struct B {
    B() {}
    B( int x ) {}
};

struct A : public B {
    A() {}    // calls B() implicitly
    A( int a, int b ) : B( b ) {} // calls B(int) explicitly
};
anon
+1  A: 

Not directly. There are a few ways to work around this.

From the initializer list of your class' constructor, you can call a constructor on any base class, and on all member variables.

So you can usually refactor your class and split it into several smaller ones to solve the problem. The commonly executed code can be placed in a member object or perhaps a base class. Then each of the main class' constructors just have to decide which construcotr to use to initialize that member.

class B {
  B() {  }
  B(int b) { DoSomething(); }
}
class A{
  A(int a = 5) : b(a) { } // call B's constructor which does something
  A() : b() {} // call B's constructor which does nothing

  B b;
};
jalf