Reputation: 45
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
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;
}
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
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