工厂函数必须是类的静态成员或友元;返回智能指针(优先unique_ptr);基类构造函数应设为protected以支持继承;构造中不可调用虚函数,应改用init()或工厂内完成初始化。

工厂函数必须是类的静态成员或友元
私有构造函数会阻止外部代码调用 new ClassName() 或栈上声明 ClassName obj;,所以工厂函数不能是普通全局函数——它必须能访问私有构造函数。常见做法只有两种:
• 声明为 static 成员函数(最常用)
• 声明为 friend 函数(适合跨类协作,如序列化器、测试桩)
如果写成普通非静态成员函数,它仍需要先有对象才能调用,而对象又无法创建,直接形成逻辑死锁。
返回智能指针而非裸指针是现代 C++ 的硬性要求
裸指针返回(如 ClassName*)会把内存管理责任甩给调用方,极易导致泄漏或重复释放。正确做法是统一返回 std::unique_ptr<ClassName> 或 std::shared_ptr<ClassName>:
• 用 std::make_unique<ClassName>() 构造,自动调用私有构造函数
• 工厂内部完成所有权转移,调用方无需 delete
• 若返回值需共享生命周期,才选 shared_ptr;否则优先 unique_ptr
注意:不能返回栈对象的 std::unique_ptr(比如 make_unique<T>() 内部必须 new),否则编译失败。
构造函数私有化后,继承关系要小心处理
如果基类构造函数私有,派生类无法隐式调用其构造函数,会导致编译错误 error: 'ClassName::ClassName()' is private within this context。
解决路径只有两条:
• 把工厂函数设为 friend,并在派生类中显式调用基类私有构造(不推荐,破坏封装)
• 将基类构造函数改为 protected(更合理),仅允许派生类调用,同时保持对外不可见
• 或者彻底放弃继承,改用组合 + 工厂委托(例如 ShapeFactory::createCircle() 内部 new Circle,而 Circle 自己控制构造)
工厂函数里别在构造过程中调用虚函数
这是最容易被忽略的陷阱:在私有构造函数内部调用虚函数,实际调用的是基类版本(因为派生类部分尚未构造)。即使工厂函数返回的是派生类指针,也救不回这个缺陷。
正确做法:
• 把初始化逻辑从构造函数中剥离,放到一个 init() 成员函数里
• 工厂函数创建对象后,立即调用该 init()(此时虚表已就绪)
• 或者干脆让工厂函数返回对象前,先完成所有可变行为的设置(如传入配置参数、回调函数)
立即学习“C++免费学习笔记(深入)”;


















