无缘无故由指针返回的责任链

Chain of responsibility going back by pointers for no reason

所以我有一个任务是开一家商店 class,产品 class 一个篮子 class bla bla bla,我做了所有这些,经过测试,一切正常,并且这与问题无关。现在我要做的是创建折扣和责任链,比如说我创建了 3 个折扣,它会通过指针检查哪个是合适的。所以我做到了,它确实有效,当我调试时我检查过,它停止在它需要的折扣上,return告诉我应用折扣后的价格但是然后它不知何故通过指针和return再次调用我不需要的东西。在展示代码后,我会更清楚地说明这一点,并提供示例。所以这是我的 Discount.h,它包含指向下一个折扣的指针和在所有这些中发挥作用的主要虚拟 countDiscount(); 函数。

#ifndef DISCOUNT_HEADER
#define DISCOUNT_HEADER

#include "Basket.h"

class Discount
{
public:
    Discount():next(NULL){}
    virtual int countDiscount(Basket b) = 0;
    void nextDiscount(Discount* nextDisc) { next = nextDisc; }
protected:
    Discount* next;
};

#endif

所以,然后我不得不做很多折扣类型,所以我从固定折扣开始,假设我有 FixatedDiscount(100, 15),所以当这个人的篮子里的东西价值超过 100,然后折扣被应用,它只从他的总价值中减去 15。因此,如果他购买了 110 美元,那么折扣适用,结果是 110 - 15= 95。这就是 FixatedDiscount.h

#ifndef FIXATED_HEADER
#define FIXATED_HEADER

#include "Discount.h"

class FixatedDiscount:public Discount
{
public:
    FixatedDiscount(int l, int d) : limit{ l }, discount{ d } {}
    int countDiscount(Basket b);
private:
    int limit;
    int discount;
};

#endif

这是FixatedDiscount.cpp

#include "FixatedDiscount.h"
#include <iostream>

int FixatedDiscount::countDiscount(Basket b) {
    int totalPrice = b.countPrice(); //this method just counts the value of the basket which for our example is 120
    if (totalPrice >= limit) {
        totalPrice -= discount;
        std::cout << "Handled when limit is " << limit << " and discount is: " << discount << " returning total price: " << totalPrice << std::endl;
    }
    else if (next != NULL) {
        next->countDiscount(b);
    }
    else {
        std::cout << "I am the last handler" << std::endl;
    }
    return totalPrice;
}

假设我有 3 个折扣,FixatedDiscount(150, 20);FixatedDiscount(100, 15)FixatedDiscount(50, 10)。在我的示例中,我将制作一个价值 120 的篮子,因此它应该跳过第一个折扣并继续进行第二个折扣,因为他购物超过 100 并且应用了 15 的折扣但他没有达到 150 以获得折扣20.

#include <iostream>
#include "Product.h"
#include "Basket.h"
#include "Discount.h"
#include "FixatedDiscount.h"
#include <vector>

int main()
{
    Product* p1 = new Product("banana", 20, "fruit");
    Product* p2 = new Product("coconut", 35, "fruit");
    Product* p3 = new Product("watermelon", 45, "vegetable");
    Product* p4 = new Product("cucumber", 20, "vegetable");
    Product* p5 = new Product("butter", 30, "dairy");
    Product* p6 = new Product("milk", 40, "dairy");
    std::vector<Product*> catalog{ p1, p2, p3, p4, p5, p6 };

    Basket basket;
    basket.insert(catalog[1]);
    basket.insert(catalog[2]);
    basket.insert(catalog[5]); //All of these 3 products make up to value of 120

    Discount* fixated1 = new FixatedDiscount(150, 20);
    Discount* fixated2 = new FixatedDiscount(100, 15);
    Discount* fixated3 = new FixatedDiscount(50, 10); //made these 3 discounts
    fixated1->nextDiscount(fixated2);
    fixated2->nextDiscount(fixated3); //linked by pointers these 3 discounts
    std::cout << "Price with the discount: " << fixated1->countDiscount(basket) << std::endl;
}

正如您在 FixatedDiscount.cpp 中看到的那样,我做了一个简单的 cout 来检查达到了哪个折扣,它说 Handled when limit is 100 and discount is: 15, returning total price: 105 应该是!但是然后,它以某种方式再次通过 countDiscount 函数和 returns 120,这是没有应用折扣的价格,这怎么可能?它不会达到第三次折扣,但不知何故它再次通过该功能 returns 120,所以我的理论是当它达到第二次折扣时它 return 给我我想要的东西是 105 因为应用了 15 的折扣,然后它返回到第一个指针,这是第一个折扣,并且由于 120 不超过 150 它不应用折扣并且 return 是我120. 为什么它不return me what I want and stop?为什么它再次通过该函数可能会通过指针返回并再次应用已经检查过但不应再检查的折扣。

int FixatedDiscount::countDiscount(Basket b) {
    int totalPrice = b.countPrice(); //this method just counts the value of the basket which for our example is 120
    if (totalPrice >= limit) {
        totalPrice -= discount;
        std::cout << "Handled when limit is " << limit << " and discount is: " << discount << " returning total price: " << totalPrice << std::endl;
    }
    else if (next != NULL) {
        next->countDiscount(b);
    }
    else {
        std::cout << "I am the last handler" << std::endl;
    }
    return totalPrice;
}

在调用 next->countDiscount(b); 之后,函数不会 return,它 returns totalPrice 应用折扣后未修改。您应该在此处分配 return 值以使折扣生效。

totalPrice = next->countDiscount(b); 应该 return 105.