Search code examples
c++polymorphismoperator-overloading

Access member elements of derived class from overriden


How do I access the derived class after overriding the copy operator overload function?

I'm new to OOP C++ so I'm not sure if defining operator overloads as pure virtual works; otherwise, how would I enforce them to be defined in derived classes?

The example here I used is of a Matrix interface and a row-major specific implementation.

class IMatrix
{
public:
    virtual IMatrix& operator=(const IMatrix& matrix) = 0;
};

class RMMatrix : public IMatrix
{
    long double* data;
public:
    RMMatrix& operator=(const IMatrix& other) override
    {
        // how to get access to data here then ? 
    };
};

Solution

  • As mentioned in the comments, you can use a dynamic_cast on the passed reference to test if it refers to an actual RMMatrix object. Something like this:

        RMMatrix& operator=(const IMatrix& other) override {
            const RMMatrix& test = dynamic_cast<const RMMatrix&>(other);
            data = test.data;
            return *this; // return a reference to "this" object!
        }
    

    However (also noted in the comments), the dynamic_cast to a reference will throw an exception if it fails (i.e. if the passed argument is not a reference to an RMMatrix).

    If you want to avoid throwing an exception, and add some other error-handling behaviour, then you can use a pointer dynamic_cast on the address of the passed argument. This will return nullptr on failure, rather than throwing an exception:

    class IMatrix {
    public:
        virtual IMatrix& operator=(const IMatrix& matrix) = 0;
        virtual ~IMatrix() = default; // We should add a VIRTUAL destructor!
    };
    
    class RMMatrix : public IMatrix {
        long double* data;
    public:
        RMMatrix& operator=(const IMatrix& other) override {
            const RMMatrix* testPtr = dynamic_cast<const RMMatrix*>(&other); // Test cast the address!
            if (testPtr != nullptr) { // Passed argument is a VALID reference...
                data = testPtr->data;
                // You would really need something safer here, rather than just copying the data pointer!
            }
            else { // Passed argument is NOT a reference to an RMMatrix...
                // Handle 'error': Leave "data" unchanged, set it to "nullptr", or throw an exception?
                //...
            }
            return *this; // return a reference to "this" object!
        }
        ~RMMatrix() override { // Override VIRTUAL destructor!
            delete data; // Maybe?
        }
    };