如果来自同一基础 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"; }
};