Reputation: 2704
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
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
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
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
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