如何将类名作为变量实现派生类的延迟初始化?
问题描述
尝试遵循DRY原则封装父类/派生类的初始化逻辑时遇到两个问题:
- 无法动态指定要初始化的派生类(类名不能作为变量使用)
- 当前封装实现每次调用函数都会初始化新对象,无法做到仅在指针为空时才初始化
以下是相关代码示例:
类声明
#include <iostream> class parent { private: int m_number; public: parent() {} virtual void say_hello() { std::cout << "Hello. This is parent class!" << std::endl; } ~parent() {} }; class derived1 : public parent { public: derived1(){} void say_hello() override { std::cout << "Hello. This is first derived class!" << std::endl; } ~derived1(){} }; class derived2 : public parent { public: derived2() {} void say_hello() override { std::cout << "Hello. This is second derived class!" << std::endl; } ~derived2() {} };
枚举状态
enum OutputMethod { STATE_NONE, STATE_CLASS, STATE_EXIT };
测试动作函数
#include <Windows.h> #define VK_L_C 0x43 #define VK_L_N 0x4E void action(OutputMethod &state) { if (GetKeyState(VK_L_C) < 0) { state = STATE_CLASS; } else if (GetKeyState(VK_L_N) < 0) { state = STATE_NONE; } else if (GetKeyState(VK_ESCAPE) < 0) { state = STATE_EXIT; } }
原始主函数逻辑
#include <iostream> #include <string> int main(void) { derived1 *p_derived = nullptr; OutputMethod out_method; out_method = STATE_NONE; while (out_method != STATE_EXIT) { // Actions (C-class, N-none, ESC-endloop) action(out_method); //--------BEGINING of desired function---------- if (out_method == STATE_NONE) { std::cout << "Hello from main!" << std::endl; } else if (out_method == STATE_CLASS) { if (p_derived == nullptr) { // 问题1:无法动态替换derived1为其他派生类 p_derived = new derived1(); } p_derived->say_hello(); } if (out_method == STATE_NONE) { if (p_derived != nullptr) { delete p_derived; p_derived = nullptr; } } //-------------END of desired function---------- } if (p_derived != nullptr) { delete p_derived; p_derived = nullptr; } std::string exit = ""; std::getline(std::cin, exit); return 0; }
尝试的封装函数(存在问题)
void output_state(parent *p_variable, parent* p_new, OutputMethod state_0, OutputMethod state_1, OutputMethod &state) { if (state == state_0) { std::cout << "Hello from main!" << std::endl; } else if (state == state_1) { if (p_variable == nullptr) { // 问题2:p_new是提前创建的对象,每次调用函数都会新建,导致内存泄漏 p_variable = p_new; } p_variable->say_hello(); } if (state == state_0) { if (p_variable != nullptr) { delete p_variable; p_variable = nullptr; } } }
调用方式(存在问题)
... derived1 *p_derived = nullptr; OutputMethod out_method; out_method = STATE_NONE; while (out_method != STATE_EXIT) { // Actions (C-class, N-none, ESC-endloop) action(out_method); // 每次调用都会执行new derived1(),即使指针不为空 output_state(p_derived, new derived1(), STATE_NONE, STATE_CLASS, out_method); } ...
解决方案
通过传递对象创建逻辑(工厂回调)和传递指针的引用可以同时解决两个问题:
1. 修改封装函数,适配动态创建与指针更新
使用std::function传递派生类的创建逻辑,同时将指针参数改为引用类型,确保函数内的修改能同步到外部变量:
#include <functional> void output_state(parent*& p_variable, const std::function<parent*()>& creator, OutputMethod state_0, OutputMethod state_1, OutputMethod& state) { if (state == state_0) { std::cout << "Hello from main!" << std::endl; // 切换状态时销毁对象 if (p_variable != nullptr) { delete p_variable; p_variable = nullptr; } } else if (state == state_1) { // 仅在指针为空时调用创建逻辑 if (p_variable == nullptr) { p_variable = creator(); } p_variable->say_hello(); } }
2. 主函数中调用封装函数
传递对应派生类的创建回调,即可动态切换要初始化的类:
#include <iostream> #include <string> #include <functional> int main(void) { parent* p_derived = nullptr; // 改为parent*适配多态 OutputMethod out_method = STATE_NONE; while (out_method != STATE_EXIT) { action(out_method); // 传递derived1的创建逻辑,切换为derived2只需替换回调内容 output_state(p_derived, [](){ return new derived1(); }, STATE_NONE, STATE_CLASS, out_method); } // 清理剩余对象 if (p_derived != nullptr) { delete p_derived; p_derived = nullptr; } std::string exit = ""; std::getline(std::cin, exit); return 0; }
3. 额外优化:用智能指针避免手动内存管理
使用std::unique_ptr自动管理内存,无需手动调用delete,降低内存泄漏风险:
#include <memory> void output_state(std::unique_ptr<parent>& p_variable, const std::function<parent*()>& creator, OutputMethod state_0, OutputMethod state_1, OutputMethod& state) { if (state == state_0) { std::cout << "Hello from main!" << std::endl; // 智能指针自动销毁对象 p_variable.reset(); } else if (state == state_1) { if (!p_variable) { p_variable.reset(creator()); } p_variable->say_hello(); } } // 主函数调用示例 int main(void) { std::unique_ptr<parent> p_derived; OutputMethod out_method = STATE_NONE; while (out_method != STATE_EXIT) { action(out_method); output_state(p_derived, [](){ return new derived1(); }, STATE_NONE, STATE_CLASS, out_method); } std::string exit = ""; std::getline(std::cin, exit); return 0; }
关键改进点
- 动态指定派生类:通过
std::function传递创建逻辑,无需硬编码类名,切换派生类仅需修改回调内容。 - 避免重复创建:仅在指针为空时执行创建逻辑,不会每次调用函数都新建对象。
- 指针引用传递:确保函数内对指针的修改同步到外部变量,解决原封装中指针无法正确更新的问题。
- 智能指针优化:自动管理内存,消除手动
delete带来的内存泄漏风险。
内容的提问来源于stack exchange,提问作者skrovno_CZ
相关产品推荐
相关产品推荐

