I have an abstract base class(X) with A & B derived classes.
I have a class method in X that is inherited by both classes A & B.
I want the method to be able to throw an exception if two different derived class objects interact with each other.
Here is a contrived example:
class Food{
public:
int count;
void combine(Food* a) {
this->count = a->count;
}
};
class Orange : Food {
public:
Orange(int x) {
count = x;
}
};
class Apple : Food{
public:
Apple(int x) {
count = x;
}
};
int main() {
Food* basket_apples = new Apple(5);
Food* basket_oranges = new Orange(4);
Food* crate_oranges = new Orange(10);
crate_oranges.combine(basket_oranges);//should work fine
crate_oranges.combine(basket_apples); //should produce error
}
A solution I considered is to override the combine method in both derived classes but that violates DRY(Don't repeat yourself).
I want to know if there are any other options to solve this issue.
CodePudding user response:
You can check that in the combine function :
void combine(Food const& a) // You should pass your argument by const ref
{
assert(typeid(*this) == typeid(a)); // This checks ONLY IN DEBUG !
this->count = a.count;
}
If you want to manage the error, use exception or return value :
void combine(Food const& a)
{
if(typeid(*this) != typeid(a))
throw std::runtime_error("Invalid combined types");
this->count = a.count;
}
int combine(Food const& a)
{
if(typeid(*this) != typeid(a))
return 1;
this->count = a.count;
return 0;
}
Maybe you should transfert the counter ?
void combine(Food& a) // Passing by non-const reference
{
assert(typeid(*this) == typeid(a));
this->count = a.count;
a.count = 0;
}
Note: As said by user17732522, your member function combine
should be virtual and the class should better manage the inheritence. I suggest this :
class Food
{
protected:
std::size_t count; // You want this value >= 0
public:
Food(std::size_t count_) : count(count_) {}
Food(Food const& f) : count(f.count) {}
virtual ~Food() {}
virtual std::string name() const = 0;
virtual void combine(Food const& a)
{
assert(typeid(a) == typeid(*this));
this->count = a.count;
}
};
class Orange : public Food
{
public:
Orange(std::size_t x) : Food(x) {}
Orange(Orange const& o) : Food(o) {}
virtual ~Orange() {}
virtual std::string name() const { return "orange"; }
};
class Apple : public Food
{
public:
Apple(std::size_t x) : Food(x) {}
Apple(Apple const& a) : Food(a) {}
virtual ~Apple() {}
virtual std::string name() const { return "apple"; }
};