如果来自同一基础 class 的两个不同的派生 class 对象相互交互,如何抛出异常?
How to throw an exception if two different derived class objects from the same base class interact with each other?
我有一个抽象基础 class(X),A 和 B 派生 classes。
我在 X 中有一个 class 方法,它被 classes A 和 B 继承。
我希望该方法能够在两个不同的派生 class 对象相互交互时抛出异常。
这是一个人为的例子:
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
}
我考虑的一个解决方案是在两个派生的 classes 中重写 combine 方法,但这违反了 DRY(不要重复你自己)。
我想知道是否有其他方法可以解决这个问题。
您可以在组合函数中检查:
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;
}
如果要管理错误,请使用异常或 return 值:
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;
}
也许你应该转移柜台?
void combine(Food& a) // Passing by non-const reference
{
assert(typeid(*this) == typeid(a));
this->count += a.count;
a.count = 0;
}
注意:正如 user17732522 所说,您的成员函数 combine
应该是虚拟的,class 应该更好地管理继承。我建议:
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"; }
};
我有一个抽象基础 class(X),A 和 B 派生 classes。
我在 X 中有一个 class 方法,它被 classes A 和 B 继承。
我希望该方法能够在两个不同的派生 class 对象相互交互时抛出异常。
这是一个人为的例子:
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
}
我考虑的一个解决方案是在两个派生的 classes 中重写 combine 方法,但这违反了 DRY(不要重复你自己)。
我想知道是否有其他方法可以解决这个问题。
您可以在组合函数中检查:
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;
}
如果要管理错误,请使用异常或 return 值:
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;
}
也许你应该转移柜台?
void combine(Food& a) // Passing by non-const reference
{
assert(typeid(*this) == typeid(a));
this->count += a.count;
a.count = 0;
}
注意:正如 user17732522 所说,您的成员函数 combine
应该是虚拟的,class 应该更好地管理继承。我建议:
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"; }
};