Florian
Florian

Reputation: 45

Constructor not called the expected number of times

Here is the code which causes a problem:

class Base
{
public:
    virtual void fun()
    {
        cout<<"Base";
    }
};
class Der:public Base
{
    Base &pb;
public:
    Der(Base&b):pb(b){}
    virtual void fun()
    {
        cout<<"Der...";
        pb.fun();
    }
};
int main()
{
    Der(Der(Base())).fun();
    return 0;
}

Run this code,and the result shows "Der...Base..."! This is so amazing, I can't figure it out why the result is not "Der...Der...Base" which is logically right?! Then I replace the member in class Der Base&pb with Base*pb and change the code into legal, finnaly the output is right which is "Der...Der...Base"! I debug the code and find that when I use Base&pb, the constructor of Der only ran once while use Base*pb, the constructor ran twice correctly! Any one who can explain to me what had happened and why?

Upvotes: 0

Views: 97

Answers (2)

Vlad
Vlad

Reputation: 35594

In addition to the @icepack's answer and the following discussion in the comments (summary: the code Der(der) is a cast, which may or may not be realized using constructor; in your case it's not), a workaround for you: you should make your intention clear by not using the constructor.

I would rewrite your code into something like this:

class Base
{
public:
    virtual void fun()
    {
        cout<<"Base";
    }
};

class Der:public Base
{
    Base &pb;
    Der(Base& b) : pb(b) {}
public:
    static Der Decorate(Base&& b){ return Der(b); }
    virtual void fun()
    {
        cout<<"Der...";
        pb.fun();
    }
};

int main()
{
    Der::Decorate(Der::Decorate(Base())).fun();
    return 0;
}

(outputs: Der...Der...Base).


Changing the code to accept the pointer is easy:

class Base
{
public:
    virtual void fun()
    {
        cout << "Base";
    }
};

class Der : public Base
{
    Base* pb;
    Der(Base* b) : pb(b) {}
public:
    static Der Decorate(Base* b){ return Der(b); }
    virtual void fun()
    {
        cout << "Der...";
        pb->fun();
    }
};

int main()
{
    Der::Decorate(&Der::Decorate(&Base())).fun();
    return 0;
}

Upvotes: 0

SomeWittyUsername
SomeWittyUsername

Reputation: 18368

In Der(Der(Base())).fun() expression the inner Der(Base()) yields an rvalue - the compiler optimizes the code by using copy elision and removes unnecessary copying of objects.

Upvotes: 1

Related Questions