Why C++ standard allow object slice ?
Please don't explain c++ object slice concept to me as I knew that.
I am just wondering what's the intention behind this c++ feature(object slice) design ?
To get novice more bugs?
Wouldn't it be more type safe for c++ to prevent object slice ?
Below is just a standard and basic slice example:
class Base{
public:
virtual void message()
{
MSG("Base ");
}
private:
int m_base;
};
class Derived : public Base{
public:
void message()
{
MSG("Derived ");
}
private:
int m_derive;
};
int main (void)
{
Derived dObj;
//dObj get the WELL KNOWN c++ slicing below
//evilDerivedOjb is just a Base object that cannot access m_derive
Base evilDerivedOjb = dObj; //evilDerivedObj is type Base
evilDerivedOjb.message(); //print "Baes" here of course just as c++ standard says
}
Thanks in advance.
================================================================================= After reading all the answers and comments I think I should express my question better in the first place but here it comes:
When there is a is-a relationship(public inheritnace), instead of private/protected inheritance , you can do the following:
class Base{
public:
virtual void foo(){MSG("Base::foo");}
};
class Derived : public Base{
public:
virtual void foo(){MSG("Derived::foo");}
};
int main (void)
{
Base b;
Derived d;
b = d; //1
Base * pB = new Derived(); //2
Base& rB = d; //3
b.foo(); //Base::foo
pB->foo(); //Derived::foo
rB.foo(); //Derived::foo
}
It's well known that only 2 & 3 works polymorphically while one is the infamous object slicing which produce nothing but a bug !
Note 1, 2 and 3 NEED is-a relationship to work.
If you are using private/protect inheritance, you will get compile error for all of them :
'type cast' : conversion from 'Derived *' to 'const Base &' exists, but is inaccessible
'type cast' : conversion from 'Derived *' to 'Base *' exists, but is inaccessible
'type cast' : conversion from 'Derived *' to 'Base &' exists, but is inaccessible
So my question(original intention) was to ask would it be better if c++ standard make 1 a compile error while keep allowing 2 and 3 ?
Hope I have expressed my question better this time.
Thanks
It's allowed because of is-a
relationship.
When you publicly1 derive Derived
from Base
, you're annoucing to the compiler that Derived
is a Base
. Hence it should be allowed to do this:
Base base = derived;
and then use base
as it is. that is:
base.message(); //calls Base::message();
Read this:
1. If you privately derive Derived
from Base
, then it is has-a
relationship. That is sort of composition. Read this and this.
However, in your case, if you don't want slicing, then you can do this:
Base & base = derived;
base.message(); //calls Derived::message();
From your comment :
Wouldn't it better for C++ to prevent object slicing while only allow the pointer/reference to work for is-a relationshp ???
No. Pointer and Reference doesn't maintain is-a
relationship if the base has virtual function(s).
Base *pBase = &derived;
pBase->message(); //doesn't call Base::message().
//that indicates, pBase is not a pointer to object of Base type.
When you want one object of one type to behave like an object of it's base type, then that is called is-a
relationship. If you use pointer or reference of base type, then it will not call the Base::message()
, which indicates, pointer or reference doesn't have like a pointer or reference to an object of base type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With