工厂函数应返回std::unique_ptr更安全,因其自动管理内存、支持多态且禁止拷贝;基类析构函数必须为virtual;字符串类型标识易出错,推荐枚举;模板工厂适用于编译期确定类型的轻量场景。

工厂函数返回指针还是引用更安全
直接返回 new 出来的裸指针是 C++ 工厂最常见也最危险的写法。调用方一忘 delete,就内存泄漏;多删一次,程序当场崩。现代 C++ 的解法很明确:返回 std::unique_ptr。
- 用
std::make_unique<concretetype>()</concretetype>构造,自动管理生命周期,不用手写new/delete - 工厂接口返回
std::unique_ptr<base>,既支持多态,又禁止拷贝(避免误传、误存) - 如果真需要共享所有权(比如多个模块都要持有该对象),才考虑
std::shared_ptr,但得清楚代价:引用计数开销 + 循环引用风险
基类析构函数没加 virtual 会出什么问题
这是工厂模式下必踩的坑——对象能创建,也能调用虚函数,但一旦通过基类指针销毁,派生类的析构函数根本不会执行。
- 现象:
Base* p = factory.create("A"); delete p;—— 派生类的资源(文件句柄、堆内存、锁等)全没释放 - 原因:C++ 规定,只有基类析构函数是
virtual,delete才会触发完整的析构链 - 修复:基类析构函数必须声明为
virtual ~Base() = default;,哪怕函数体为空
用字符串做类型标识符时要注意什么
用 std::string 当参数决定创建哪个子类,看着灵活,实际容易埋雷。
- 大小写敏感:
"button"和"Button"是两个不同类型,建议统一转小写或用枚举替代 - 拼写错误无编译检查:输成
"buton",工厂返回空指针,运行时报错,不如用enum class WidgetType { Button, Checkbox }; - 性能影响:每次都要字符串比较,对高频创建场景(如渲染循环中),改用
switch+ 枚举更快更安全
模板工厂比虚函数工厂更适合哪些场景
不是所有工厂都得靠继承和虚函数。当你不需要运行时动态决定类型,而是在编译期就知道要哪种对象时,模板工厂更轻量、更高效。
立即学习“C++免费学习笔记(深入)”;
- 典型场景:配置固定、构建时确定类型,比如
Factory<button>::create()</button>或make_widget<button>()</button> - 优势:零运行时开销,无虚函数表,内联友好,编译器能做更多优化
- 限制:无法把不同模板实例统一成一个接口类型(比如不能放进
std::vector),想统一管理就得回退到虚函数方案
真正难的从来不是写个能 new 出对象的函数,而是让工厂在生命周期、类型安全、扩展性和性能之间不偏科——尤其当别人开始往你的工厂里塞新类型的时候。










