-1

I have a base class Device and inherited class InputDevice. In class XYZ I have a function XYZ::setDevice(int num, Device device) that expects object Device as parameter. When I call the function setDevice() with parameter that is sublclass of Device (InputDevice) it gets converted to Device and I can't access the derived functions of derived class afterwards. So if I want to call the function of "device" in function setDevice() it calls function of Device instead of overriden function in class InputDevice. What am I doing wrong?

void XYZ::setDevice(int num, Device device) {

    printf("%s\n", typeid(device).name());                    //this prints "Device"
    this->devices[num] = device;
}

XYZ::XYZ() {
    printf("%s\n", typeid(InputDevice(cin)).name());          //this prints "InputDevice"

    setDevice(STANDARD_INPUT_DEVICE, InputDevice(cin));
    printf("%s\n", typeid(devices[0]).name());
}
  • 1
    Change `void XYZ::setDevice(int num, Device device) {` to take the parameter as reference: `void XYZ::setDevice(int num, Device& device) {` – πάντα ῥεῖ Nov 21 '22 at 09:27
  • 3
    This is called *object slicing*. The fundamental problem is not `setDevice` it's `this->devices[num] = device;` which is also going to have the same object slicing problem. You need to store pointers to your devices (preferably smart pointer, like `std::unique_ptr`). – john Nov 21 '22 at 09:30

1 Answers1

-2

I don't see the full code, but instead of storing objects, you should store pointers. Your devices array should be vector or array of Device pointers.

Here's a fully working example.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Device {
public:
    virtual string getName() const {
        return string("Device");
    }
};

class InputDevice : public Device {
public:
    string getName() const override{
        return string("InputDevice");
    }
};

class XYZ {
    Device* devices[10];

public:

    void setDevice(int num, Device *device)
    {
        devices[num] = device;
        cout << "Name : " << device->getName();
    }

};

int main()
{
    Device* dev1 = new Device();
    Device* dev2 = new Device();
    InputDevice* dev3 = new InputDevice();
    XYZ xyz;
    xyz.setDevice(0, dev1);
    xyz.setDevice(1, dev2);
    xyz.setDevice(2, dev3);
}
brmRush
  • 67
  • 7
  • That way i won't be able to pass in object of class OutputDevice – GabrijelOkorn Nov 21 '22 at 09:34
  • The code is now legal, but clearly does not solve the OPs problem since they are going to have the same problem of an `InputDevice` being converted to a `Device` when you assign the object to the `devices` array. – john Nov 21 '22 at 09:36
  • I don't see the full code, but instead of storing objects, you should store pointers. Your devices array should be vector or array of Device pointers. – brmRush Nov 21 '22 at 09:36
  • @brmRush That comment should be your answer, instead of the code above. – john Nov 21 '22 at 09:37
  • Thanks for comments, you're right I should've done that first. Fixed it. – brmRush Nov 21 '22 at 09:38
  • Hope it fits right now. Sorry I'm new here, just trying to help. – brmRush Nov 21 '22 at 09:40
  • It works now after you edited answer, thanks. So if I understand correctly the problem was object slising, right? – GabrijelOkorn Nov 21 '22 at 12:18