Rob Falck
Rob Falck

Reputation: 2704

Changing an object from one derived class to another

I have a couple of classes that share a common base class, with the exception that they differ in the way their methods work. So in the example below, Adder and Multiplier are the same except for the way in which their calculation is performed.

Is there a way to change "a" to a Multiplier on the fly? Do I need to implement methods which convert derived classes to each other? e.g. something like

a = a.asMultiplier()?

As you can see in the code below I tried reinterpret_cast to a Multiplier, with no luck, it still acts like an Adder. (gcc OS X v4.2.1)

#include <iostream>


class Base {
protected:
    int a,b;    
public:
    Base(int a, int b) {
        this->a = a;
        this->b = b;
    }  
    virtual ~Base() { }    
    virtual int calculate() = 0;
};


class Adder : public Base {    
public:
    Adder(int a, int b) : Base(a, b) {

    }      
    int calculate() {
        return this->a + this->b;
    }
};


class Multiplier : public Base {    
public:
    Multiplier(int a, int b) : Base(a, b) {    
    }  

    int calculate() {
        return this->a * this->b;
    }
};



int main() {

    Base* a = new Adder(3,4);
    Base* m = new Multiplier(3,4);

    std::cout << "Adder gives " << a->calculate() << std::endl;
    std::cout << "Multiplier gives " << m->calculate() << std::endl;

    a = reinterpret_cast<Multiplier*>(a);

    std::cout << "Now adder gives " << a->calculate() << std::endl;

    delete a;
    delete m;
    return 0;
}

Upvotes: 4

Views: 6087

Answers (4)

W. Goeman
W. Goeman

Reputation: 1714

The best thing that comes up to me to solve this, is implementing a copy constructor, taking the base class:

class Multiplier : public Base {    
public:
    Multiplier(int a, int b) : Base(a, b) {    
    }  

    explicit Multiplier(const Base& iBase) : Base(iBase.a, iBase.b) {    
    }  

    int calculate() {
        return this->a * this->b;
    }
};

But since I am not the most advanced c++ developer here, it might not be correct or other people might have a better idea, just trying :)

Upvotes: 7

mathematician1975
mathematician1975

Reputation: 21351

It is probably a good idea to change your design. In general I would say that it is a good idea to used inheritance when there is some kind of commonality shared by base and derived classes, not only in terms of data, but in terms of behaviour. Whilst not being very helpful advice directly I would suggest maybe reading some books on object oriented design principles. Trying to cast types in the way you are really makes no sense.

Upvotes: 2

Attila
Attila

Reputation: 28762

This seems to me that you would need utility classes that operate on data: Change your base class to a Data class whose purpose is only to store the data and pass the data explicitly to the Adder, Multiplier etc. classes.

You can still use inheritance in the utility classes if it makes sense after the above refactoring: in this case base would also operate on a Data object, instead of being the Data itself

Upvotes: 4

Vlad
Vlad

Reputation: 35594

I would propose to decouple the object's data from its operations. This way you can easily construct one object from another, overtaking the data. So your "conversion" will look like this: Multiplier m = new Multiplier(a);

Doing it the way you are asking for is impossible in C++.

Upvotes: 5

Related Questions