派生类能否调用带可选参数的基类构造函数并自动映射参数?
关于C++派生类调用基类构造函数的参数映射问题
问题背景
假设有如下基类构造函数:
class Base{ public: Base(std::optional<type0> a, std::optional<type1> b, std::optional<type2> c, std::optional<type3> d) : _a(a), _b(b), _c(c), _d(d) { } private: std::optional<type0> _a; std::optional<type1> _b; std::optional<type2> _c; std::optional<type3> _d; };
派生类能否仅传入部分参数调用该构造函数,并自动将参数映射到对应的基类成员?例如如下派生类(补充了必要的继承关系):
class Derived : public Base { Derived(std::optional<type1> b, std::optional<type3> d) : Base(b, d) { } };
能否自动将b映射到_b、d映射到_d?
结论:不行,C++默认不支持按参数名称自动映射的构造函数调用
C++的构造函数参数匹配是严格按位置顺序进行的,和参数名称无关。你写的Derived构造函数里调用Base(b, d),会把b传给Base构造函数的第一个参数a(类型为std::optional<type0>),把d传给第二个参数b(类型为std::optional<type1>),这会直接触发类型不匹配的编译错误。
实现需求的几种可行方法
1. 给基类构造函数添加默认参数或重载构造函数
你可以修改基类,给构造函数的参数设置默认值为std::nullopt,这样派生类可以只传需要的参数:
class Base{ public: // 带默认参数的构造函数 Base(std::optional<type0> a = std::nullopt, std::optional<type1> b = std::nullopt, std::optional<type2> c = std::nullopt, std::optional<type3> d = std::nullopt) : _a(a), _b(b), _c(c), _d(d) {} private: std::optional<type0> _a; std::optional<type1> _b; std::optional<type2> _c; std::optional<type3> _d; }; class Derived : public Base { public: // 显式指定参数位置,其余用默认值 Derived(std::optional<type1> b, std::optional<type3> d) : Base(std::nullopt, b, std::nullopt, d) {} };
或者直接给基类重载一个只接受b和d的构造函数:
class Base{ public: // 保留原构造函数 Base(std::optional<type0> a, std::optional<type1> b, std::optional<type2> c, std::optional<type3> d) : _a(a), _b(b), _c(c), _d(d) {} // 重载构造函数 Base(std::optional<type1> b, std::optional<type3> d) : _a(std::nullopt), _b(b), _c(std::nullopt), _d(d) {} private: std::optional<type0> _a; std::optional<type1> _b; std::optional<type2> _c; std::optional<type3> _d; }; class Derived : public Base { public: Derived(std::optional<type1> b, std::optional<type3> d) : Base(b, d) {} };
2. 模拟命名参数(C++20+推荐)
用一个参数结构体封装基类的所有可选参数,利用C++20的指定初始化器明确赋值,代码可读性更高:
// 定义基类参数结构体 struct BaseParams { std::optional<type0> a; std::optional<type1> b; std::optional<type2> c; std::optional<type3> d; }; class Base{ public: // 接受参数结构体的构造函数 Base(BaseParams params) : _a(params.a), _b(params.b), _c(params.c), _d(params.d) {} private: std::optional<type0> _a; std::optional<type1> _b; std::optional<type2> _c; std::optional<type3> _d; }; class Derived : public Base { public: Derived(std::optional<type1> b, std::optional<type3> d) : Base({.b = b, .d = d}) {} // 直接指定要赋值的成员,其余默认为空 };
内容的提问来源于stack exchange,提问作者callum arul
相关产品推荐
相关产品推荐

