0

I believe I have a slicing problem, and I am not sure how to fix it. I have summarized the issue from my actual program into the example below.

#include <iostream>
#include <vector>
using namespace std;

class Base {
public:
    void Use(void) {
        cout << "Using Base :(\n";
    }
};

class First_Derived : public Base {
public:
    void Use(void) {
        cout << "Using First_Derived!\n";
    }
};

class Second_Derived : public Base {
public:
    void Use(void) {
        cout << "Using Second_Derived!\n";
    }
};

class A {
public:
    vector<Base *> Base_Objects;
};

class B {
public:
    vector<Base *> Base_Objects;
};


int main() {
    // Create and populate A_Object
    A A_Object;
    A_Object.Base_Objects.push_back(new First_Derived());
    A_Object.Base_Objects.push_back(new Second_Derived());

    // Create and populate B_Object with objects in A_Object.Base_Objects
    B B_Object;
    for (vector<Base *>::iterator i = A_Object.Base_Objects.begin(); i != A_Object.Base_Objects.end(); ++i) {
        B_Object.Base_Objects.push_back(*i);
    }

    // Run the Use() function for the first object in B_Object.Base_Objects
    (*B_Object.Base_Objects[0]).Use();

    // Get command terminal to pause so output can be seen on Windows
    system("pause");
    return 0;
}

The output is Using Base :( but I expected Using First_Derived!. I believe the issue is that once the First_Derived object is stored in the Base_Objects vector, it loses it's unique Use() function, because it is getting converted to a Base type? Is there a solution to this? I have attempted to apply some of the solutions listed in What is object slicing? but I dont believe I am applying them correctly.

Community
  • 1
  • 1
halexh
  • 3,021
  • 3
  • 19
  • 19

2 Answers2

3

Moving comment to answer

Your problem is that you are using non-virtual functions (method hiding) not slicing.

Whenever define a function in a child class, it will "hide" the implementation of the same method in the parent class.

What you want to do is declare the methods as virtual:

class Base {
public:
    virtual void Use(void) {
        cout << "Using Base :(\n";
    }
};

class First_Derived : public Base {
public:
    virtual void Use(void) {
        cout << "Using First_Derived!\n";
    }
};

class Second_Derived : public Base {
public:
    virtual void Use(void) {
        cout << "Using Second_Derived!\n";
    }
};

While we're on the subject, you'll probably want to declare virtual destructors as well.

Slicing happens when you try and store a child class in the space allocated for a parent class. In this case, there is only enough space for the parent classes values, so the child's gets left behind. Funily enough, you'll usually only see this if you try and access the members...virtual function calls will STILL be called (The vtable will point to the right method call). Slicing will give you horrible stack and heap corruption errors, and make values appear weird..."undefined behaviour" as it were, but it will STILL call the correct virtual functions in the class!

IdeaHat
  • 7,641
  • 1
  • 22
  • 53
0

This isn't a slicing problem. I think you just intended Use to be virtual and it's not.

Barry
  • 286,269
  • 29
  • 621
  • 977