How to avoid slicing?

Hello,

I have problems with object slicing. I am passing a Derived instance as a parameter in my constructor. Because member variable "base" is copy constructed from this object, it is sliced - it is no longer of type Derived. How can I retain that type without using pointers?

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>

class Base
{
public:
    virtual ~Base() {};
};

class Derived : public Base
{    
public:
    ~Derived() {};
};

class MyClass
{
public:
    MyClass(int x, Base base) : x(x), base(base)
    {
     	if (!dynamic_cast<Derived*>(&(this->base)))
     	    std::cout << "This is not a Derived instance.";       
    };
    int x;
private:
    Base base;
};

int main()
{
    MyClass myclass(7, Derived());
}


As you can see, this->base is no longer of type Derived but I would like it to be it. Is this possible?
You can use references
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <string>
#include <typeinfo>

class Base
{
public:
    virtual ~Base() {};
};

class Derived : public Base
{    
public:
    ~Derived() {};
};

class MyClass
{
public:
    MyClass(int x, Base& base) : x(x), base(base)
    {
     	try {
     	    Derived& derived = dynamic_cast<Derived&>(this->base);
     	} catch (const std::bad_cast& e) {
     	    std::cout << "This is not a Derived instance.";  
     	}
     	         
    };
    int x;
private:
    Base& base;
};

int main()
{
    Derived derived;
    MyClass myclass(7, derived);
}


Edit: But the use-case for this is more limited than using pointers...
Last edited on
How can I retain that type without using pointers?
You can't. Using polymorphism requires pointers. No way around that.

The usual way to copy a polymorphic object is to have a clone() member function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Base{
public:
    virtual ~Base();
    virtual std::unique_ptr<Base> clone() = 0;
};

class Derived1 : public Base{
public:
    std::unique_ptr<Base> clone(){
        return new Derived1(*this);
    }
};

class Derived2 : public Base{
public:
    std::unique_ptr<Base> clone(){
        return new Derived2(*this);
    }
};
Last edited on
You can't. Using polymorphism requires pointers. No way around that.

I think you're forgetting that you can use references too, instead of pointers.
Forgetting for a moment that a reference to a polymorphic class will probably compile to a pointer, you can't do everything with a reference that you can with a pointer. For example, have an array of references/pointers.
Thank you for all replies.

The problem with references is that if I pass object by reference to instance of my class, this object must outlive the instance. Then, for example I could not use code like this:

1
2
3
4
int main()
{
    MyClass myclass(7, Derived());
}


I can't construct Derived in-place, because it gets freed after living constructor...
Last edited on
Topic archived. No new replies allowed.