gpt4 book ai didi

c++ - 为什么装饰器模式的实现需要一个与核心类共同的抽象父类(super class)?

转载 作者:搜寻专家 更新时间:2023-10-31 00:25:40 25 4
gpt4 key购买 nike

我正在试验 c++ 中的装饰器设计模式。但是,如果没有核心类和装饰类都继承自的抽象父类(super class),我无法实现它。

我不明白为什么需要抽象父类(super class)。

我的装饰器示例:

#include <string>
#include <iostream>
using namespace std;

// abstract superclass
class Pizza
{
public:
virtual string GetDescription() = 0;
virtual int GetCost() = 0;
};

// base class that can be extended
class Margharita: public Pizza
{
private:
string description;
int cost;
public:
Margharita(string t, int c){description = t; cost = c;}
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};

// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;

public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}

string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};

int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Margharita("Margharita", 100));
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}

给出输出:Margharita, Extra Cheese 120

如果我删除抽象父类(super class),装饰将停止工作:

#include <string>
#include <iostream>
using namespace std;

// base class that can be extended
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};

// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;

public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}

string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};

int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Pizza());
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}

在这种情况下,输出仅显示核心对象 (Pizza 100) 的属性。

为什么会这样?

最佳答案

当您删除抽象基类时,您使函数 GetDescriptionGetCost 不是虚拟的。因此,它们不是动态调度的。这就是为什么 pizza->GetDescription() 调用了 Pizza 成员函数,它是根据 静态类型解析的调用仅限披萨

你不需要有一个抽象的基础来让它再次工作,只需要动态调度,所以只需添加虚拟说明符

class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
virtual string GetDescription(){return(description);}
virtual int GetCost(){return(cost);}
};

这将允许在 ExtraCheese 中进行覆盖,以通过动态调度获取。您还可以通过使用 override 说明符帮助编译器捕获此类错误。如果你这样定义 ExtraCheese:

class ExtraCheese: public Pizza
{
private:
Pizza* pizza;

public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}

string GetDescription() override { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() override { return(pizza->GetCost() + 20); }
};

现代编译器会提示您试图覆盖未声明为虚拟的函数。这个错误很明显。

关于c++ - 为什么装饰器模式的实现需要一个与核心类共同的抽象父类(super class)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55468227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com