C++中传递参数时避免结构体向下转型的实现方案
解决带参数的操作类初始化问题
你已经定义了参数结构体、抽象操作类和工厂类,但工厂类中无法直接访问子类参数的成员(比如is_min_op),以下是具体的修正方案:
1. 完善参数结构体(添加虚析构)
首先给基类Arguments添加虚析构函数,确保子类对象能正确释放:
struct Arguments { double *data; int num_data; Arguments(double *data, int num_data) : data(data), num_data(num_data) {} virtual ~Arguments() = default; // 必须添加,避免内存泄漏 }; struct MeanOperationArguments: Arguments { MeanOperationArguments(double *data, int num_data) : Arguments(data, num_data) {} }; struct MinmaxOperationArguments: Arguments { bool is_min_op; MinmaxOperationArguments(double *data, int num_data, bool is_min_op) : Arguments(data, num_data), is_min_op(is_min_op) {} };
2. 修正操作类的实现
让每个操作类接收对应的参数子类,而非基类Arguments,并实现execute逻辑:
// 补充OP_TYPE枚举定义 enum OP_TYPE { MEAN, MINMAX }; class Operation { public: virtual void execute() = 0; virtual ~Operation() = default; // 虚析构,确保子类资源释放 }; class MeanOperation: public Operation { private: MeanOperationArguments *args; public: MeanOperation(MeanOperationArguments *args) : args(args) {} void execute() override { if (!args || args->num_data <= 0) return; double sum = 0; for (int i = 0; i < args->num_data; ++i) sum += args->data[i]; printf("均值:%.2f\n", sum / args->num_data); } }; class MinOperation: public Operation { private: MinmaxOperationArguments *args; public: MinOperation(MinmaxOperationArguments *args) : args(args) {} void execute() override { if (!args || args->num_data <= 0) return; double min_val = args->data[0]; for (int i = 1; i < args->num_data; ++i) { if (args->data[i] < min_val) min_val = args->data[i]; } printf("最小值:%.2f\n", min_val); } }; class MaxOperation: public Operation { private: MinmaxOperationArguments *args; public: MaxOperation(MinmaxOperationArguments *args) : args(args) {} void execute() override { if (!args || args->num_data <= 0) return; double max_val = args->data[0]; for (int i = 1; i < args->num_data; ++i) { if (args->data[i] > max_val) max_val = args->data[i]; } printf("最大值:%.2f\n", max_val); } };
3. 修复工厂类的类型转换问题
使用dynamic_cast进行安全的向下转型,确保只在类型匹配时创建操作对象:
class OperationFactory { public: Operation *get(OP_TYPE t, Arguments *args) { switch(t) { case MEAN: { MeanOperationArguments *mean_args = dynamic_cast<MeanOperationArguments*>(args); return mean_args ? new MeanOperation(mean_args) : nullptr; } case MINMAX: { MinmaxOperationArguments *minmax_args = dynamic_cast<MinmaxOperationArguments*>(args); if (!minmax_args) return nullptr; return minmax_args->is_min_op ? static_cast<Operation*>(new MinOperation(minmax_args)) : static_cast<Operation*>(new MaxOperation(minmax_args)); } default: return nullptr; } } };
4. 验证代码(main函数)
原main函数可以直接使用,注意添加内存释放逻辑避免泄漏:
int main() { double data[] = { 1, 2, 3, 4 }; int num_data = 4; OperationFactory operations; Arguments *mean_args = new MeanOperationArguments(data, num_data); Operation *mean_op = operations.get(MEAN, mean_args); if (mean_op) { mean_op->execute(); delete mean_op; } Arguments *min_args = new MinmaxOperationArguments(data, num_data, true); Operation *min_op = operations.get(MINMAX, min_args); if (min_op) { min_op->execute(); delete min_op; } Arguments *max_args = new MinmaxOperationArguments(data, num_data, false); Operation *max_op = operations.get(MINMAX, max_args); if (max_op) { max_op->execute(); delete max_op; } delete mean_args; delete min_args; delete max_args; return 0; }
关键注意事项
- 虚析构函数:基类
Arguments和Operation必须添加虚析构,否则子类对象无法正确释放,会导致内存泄漏。 - 安全类型转换:使用
dynamic_cast而非强制转换,避免类型不匹配时的非法内存访问。 - 可选优化:如果不需要拆分
MinOperation和MaxOperation,可以合并为一个MinmaxOperation,在execute方法中根据is_min_op分支执行逻辑,减少类的数量。
内容的提问来源于stack exchange,提问作者Gagan Ganapathy
相关产品推荐
相关产品推荐

