Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't one ctor call another ctor to initialize the object

Tags:

c++

class Foo {

 public:
  Foo() { Foo(1)}
  Foo(int x, int y = 0):i(x) {}
 private:
  int i;
}

Can anybody give me some reasonas about can I do this? If not why?

like image 229
skydoor Avatar asked Mar 16 '10 18:03

skydoor


People also ask

Can one constructor call another C++?

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.

How do you call one constructor from another?

Constructor chaining can be done in two ways: Within same class: It can be done using this() keyword for constructors in the same class. From base class: by using super() keyword to call the constructor from the base class.

Is it possible to call one constructor from another in Java?

You can call another constructor via the this(...) keyword (when you need to call a constructor from the same class) or the super(...) keyword (when you need to call a constructor from a superclass). However, such a call must be the first statement of your constructor.

Can we call the constructor more than once for object?

There can be only one special method with the name constructor in a class. Having more than one occurrence of a constructor method in a class will throw a SyntaxError error.


2 Answers

Because the language specification doesn't allow it. Just the way the language is. Very annoying if you're used to Java or other languages that allow it. However, you get used to it after a while. All languages have their quirks, this is just one of C++'s. I'm sure the writers of the specs have their reasons.

Best way around this I've found is to make a common initialization function and have both constructors call that.

Something like this:

class Foo {
public:
    Foo() {initialize(1);}
    Foo(int nX) { initialize(nx); }

private:
    void initialize(int nx) { x=nx; }
    int x;
};
like image 132
Daniel Bingham Avatar answered Sep 21 '22 10:09

Daniel Bingham


It's a language design choice.

A constructor is a one time (per-object) operation that creates a new object in uninitialized memory. Only one constructor can be called for an object, once it has completed the object's lifetime begins and no other constructor can be called or resumed on that object.

At the other end of its life a destructor can only (validly) be called once per object and as soon as the destructor is entered the object's lifetime is over.

A prinicipal reason for this is to make explicit when an object destructor will be run and what state it can expect the object to be in.

If a class constructor completes successfully then it's destructor will be called, otherwise the object's lifetime has never begun and the destructor will not be called. This guarantee can be important when an object acquires resources in its constructor that need to be released in its destructor. If the resource acquisition fails then the constructor will usually be made to fail; if the destructor ran anyway it might attempt to release an resource that had never been successfully acquired.

If you allow constructors to call each other it may not be clear if a calling or a called constructor is responsible for the resource. For example, if the calling constructor fails after the called constructor returns, should the destructor run? The called constructor may have acquired something that needs releasing or perhaps that was what caused the calling construtor to fail and the destructor shouldn't be called because the resource handle was never valid.

For simplicity of the destruction rules it is simpler if each object is created by a single constructor and - if created successfully - destroyed by a single destructor.

Note that in C++11 a constructor will be able delegate to a different constructor, but there are limitations that don't really relax the principal of one construction per object. (The prinicipal constructor can forward to a target constructor, but if it does it must not name anything else (base classes or members) in its initializer list. These will be initialized by the target constructor, once the target constructor returns the body of the prinicipal constructor will complete (further initialization). It is not possible to re-construct any bases or members, although it allows you to share constructor code between constuctors.)

like image 29
CB Bailey Avatar answered Sep 19 '22 10:09

CB Bailey