Reputation: 995
I've been trying to rewrite a program of mine to allow for inherited classes. I'm running into a problem with slicing. I originally had Parent m_parent
in my Test
class (therefore no dynamic allocation in Test), but added that thinking it'd fix my issue, but it hasn't. I don't know if I'm making my issue worse or if it's as simple as writing a copy constructor (or some other simple fix).
class Parent
{
public:
Parent();
private:
string a;
};
class Child : public Parent
{
private:
string b;
};
class Test
{
public:
Test()
{
m_parent = new Parent;
}
void testFunction(Parent &parent)
{
*m_parent = parent;
}
~Test()
{
delete m_parent;
}
private:
Parent * m_parent;
};
Doing something like this still causes slicing...
Child c("foo", "bar");
Parent * p = &c;
Test.testFunction(*p);
Upvotes: 1
Views: 497
Reputation: 26546
Yes. this line:
*m_parent = parent;
causes the object to be sliced into Parent
object regardless on what it really is.
Other than that, there are many error proned lines of code in your example, but I guess its only because it's a very specific question.
Edit: A suggestion how to avoid slicing:
template <class T>
void testFunction(T& t){
static_assert(std::is_base_of<Parent,T>::value,"only subclasses of Parent may be passed to testFunction");
delete m_parent;
m_parent = new T(t); //or: new T(std::move(t));
}
EDIT 2:
this shall work if you pass a child object as real object and not as a parent pointer , AKA testFunction(myChild)
EDIT3: @Jarod42 has a good point about the clone
method. the two of the solution can be used together
Upvotes: 2
Reputation: 218323
There are no object slicings, but m_parent
doesn't become a Child
and only string a
is copied.
If you want keep a copy in Test
, I suggest using Clone
:
class Parent
{
public:
virtual ~Parent() = default;
virtual Parent* Clone() const { return new Parent(*this); }
private:
string a;
};
class Child : public Parent
{
public:
Child* Clone() const override { return new Child(*this); }
private:
string b;
};
class Test
{
public:
void testFunction(const Parent &parent)
{
m_parent.reset(parent.Clone());
}
private:
std::unique_ptr<Parent> m_parent;
};
Upvotes: 2