原型模式代码行为分析及疑似错误代码排查请求
原型模式C++代码错误检查与行为分析
首先先把你提供的不完整代码贴出来:
class Stooge { public: virtual Stooge* clone() = 0; virtual void slap_stick() = 0; }; class Curly : public Stooge { public: Stooge* clone() { return new Curly; } void slap_stick() { cout << "Curly: suffer abuse\n"; } }; Stooge* Factory::s_prototypes[] = { 0, new Larry, new Moe, new Curly }; Stooge* Factory::make_stooge( int choice = 3 ) { return s_prototypes[ch...
一、代码中存在的明显错误
我一眼就能看到好几个会导致编译失败或者逻辑问题的点:
- 缺失必要头文件:代码里用了
cout,但没有包含<iostream>头文件,编译器根本不知道cout是什么。 - Factory类未定义:你直接使用了
Factory::s_prototypes和Factory::make_stooge,但完全没给出Factory类的定义,这是语法层面的硬伤。 - Larry和Moe类缺失实现:静态数组里实例化了
new Larry和new Moe,但这两个继承自Stooge的子类完全没定义,编译肯定会报“未定义类型”的错误。 - 函数参数名错误:
make_stooge函数声明里的参数是choice,但函数体里写的是ch(从你没写完的代码能看出来是笔误),这会导致变量未定义的编译错误。 - 命名空间问题:
cout属于std命名空间,要么写成std::cout,要么在代码开头加using namespace std;,不然编译器找不到这个符号。 - 数组越界风险:默认参数
choice = 3对应数组索引3(数组是{0, new Larry, new Moe, new Curly}),虽然这个索引是合法的,但如果传入大于3的数值,就会触发数组越界的未定义行为。
二、这段代码中原型模式的核心行为分析
虽然代码有问题,但能看出来它想实现的原型模式逻辑是清晰的:
- 抽象原型类:
Stooge作为抽象基类,定义了两个核心方法:clone()(纯虚函数,要求子类实现克隆自身的逻辑)和slap_stick()(子类的业务方法)。 - 具体原型类:比如
Curly,它实现了clone()方法,返回一个新的Curly实例——这就是原型模式的核心:通过克隆已有对象来创建新对象,而不是直接调用构造函数。 - 原型管理器(Factory类):Factory的静态数组
s_prototypes用来存储各个具体Stooge子类的原型实例(Larry、Moe、Curly的实例),make_stooge方法根据传入的选择值,克隆对应索引的原型对象并返回。这种设计的好处是:- 避免了直接依赖具体子类,实现了对象创建与使用的解耦;
- 如果需要新增Stooge子类,只需要添加新的原型到数组,修改Factory的逻辑即可,符合开闭原则;
- 克隆对象比直接创建对象更高效(尤其是对象初始化成本高的时候)。
修正后的示例代码
为了让这段代码能正常运行,我补全了缺失的部分:
#include <iostream> using namespace std; class Stooge { public: virtual Stooge* clone() = 0; virtual void slap_stick() = 0; virtual ~Stooge() {} // 虚析构函数,避免内存泄漏 }; class Larry : public Stooge { public: Stooge* clone() { return new Larry; } void slap_stick() { cout << "Larry: slap forehead\n"; } }; class Moe : public Stooge { public: Stooge* clone() { return new Moe; } void slap_stick() { cout << "Moe: poke eyes\n"; } }; class Curly : public Stooge { public: Stooge* clone() { return new Curly; } void slap_stick() { cout << "Curly: suffer abuse\n"; } }; class Factory { public: static Stooge* s_prototypes[]; static Stooge* make_stooge(int choice = 3) { if (choice < 1 || choice > 3) return nullptr; // 边界检查 return s_prototypes[choice]->clone(); } }; Stooge* Factory::s_prototypes[] = { nullptr, new Larry, new Moe, new Curly }; int main() { Stooge* stooge1 = Factory::make_stooge(1); Stooge* stooge2 = Factory::make_stooge(2); Stooge* stooge3 = Factory::make_stooge(); // 使用默认参数3 stooge1->slap_stick(); stooge2->slap_stick(); stooge3->slap_stick(); // 释放内存 delete stooge1; delete stooge2; delete stooge3; // 注意:原型实例的内存这里没释放,实际项目中需要考虑管理方式 return 0; }
内容的提问来源于stack exchange,提问作者Sijith




