0

I have the following code :

#include <iostream>
using namespace std;
class X {
public:
    X () {
        x = 0;
        cout << "1";
    }
    X (int x) {
        this->x = x;
        cout << "2";
    }
    X (double x) {
        this->x = x;
        cout << "3";
    }
    X (const X& x) {
        this->x = x.x;
        cout << "4";
    }
protected:
    int x;
};
class Y : public X {
public:
    Y () : X(10) {
        cout << "5";
    }
    Y (int p) : X(p) {
        cout << "6";
    }
    Y (const X& x) : X(x) {
        cout << "7";
    }
    Y (const X& x1, X x2) : X(x1), x(x2) {
        cout << "8";
    }
protected:
    X x;
};

int main() {
    Y y1;
    cout << endl;
    Y y2(10);
    cout << endl;
    Y y3(y1);
    cout << endl;
    Y y4(y2, y3);
    cout << endl;
}

The output of this code is :

215
216
44
4448
  • In the first two cases, I don't understand why there is the '1'. I agree that the object is built with the second X constructor and the first of Y but why the first constructor of X is called after the second one ?
  • In the third case I would like to know why there is no '7' because in my opinion the program declares a Y instance so a Y constructor should be called ?
  • In the last case, there is a '8' so that sound good to me but why there is three X constructor call whereas y2 and y3 are already declared ?

PS : I apologize for my English mistakes and I thank the people who correct me

Lodec
  • 87
  • 1
  • 8

1 Answers1

2

Y derives from X, and also contains a data member x of type X. When instantiating an object instance of Y, an X constructor must be called for both the inherited X portion of the Y class, and the x data member.

In the first 2 cases, the Y constructors you are calling are not explicitly initializing the x data member, so the compiler uses the default X() constructor to initialize it implicitly. That is where the 1 comes from.

In the 3rd case, 7 is not output because you are not constructing the y3 object with an X object as input. You are constructing it with another Y object. But you haven't explicitly defined a Y(const Y&) copy constructor, so the compiler defines an implicit copy constructor for you, which invokes the X copy constructor twice, once for the inherited X portion of the Y class, and once for the x data member.

In the last case, you see 4 being output 3 times because you are invoking the X copy constructor 3 times, two explicitly and one implicitly:

  • when passing x1 to X()
  • when passing y3 to x2 (which slices y3, because x2 is pass-by-value)
  • when passing x2 to x()
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I almost understand all your explanation, but in the first two cases I'm still not understanding which line are calling the default `x()` constructor because the line `Y () : X(10)` is used for the first case hence this line calls the constructor which take a int parameter. So why the compiler uses the default `x()` constructor whereas all the objects are built ? – Lodec Oct 01 '17 at 20:18
  • 1
    @Lodec: as I said in my answer, the first 2 cases are not initializing `Y`'s `x` data member **explicitly**, only the inherited `X` portion of the `Y` class, so the compiler is **implicitly** calling the default `X()` constructor for the `x` member. Remember, `Y` has 2 `X`s in it, not one – Remy Lebeau Oct 01 '17 at 20:33