在 C++ 的派生 class 构造函数中调用动态基础 class 构造函数
dynamic base class constructor call in derived class constructor in c++
我在库中有一个基础 class,出于兼容性原因我不想修改它。这个 class 存储了某些设置,构建后不能修改;构造时必须提供正确的参数。
我自己的代码包含一个从 class 派生的 class。派生class的构造函数的参数结构与基class的构造函数不同;参数不是简单地传递给基础 class 构造函数。
将使用三组预先确定的参数从派生的 class 构造基础 class。使用这三个中的哪一个取决于派生的 class 构造函数的参数。由于成员初始值设定项列表中需要基础 class 参数,因此需要在进入派生构造函数的主体之前做出此决定。
在这种情况下,使用需要为 Arduino (Mega) 编译的代码来完成此操作最优雅的是什么?
演示设置的伪代码:
class base{
base(type1 arg1, type2 arg2){/*do something*/}
};
class derived : base{
int variable;
derived(typeA a, typeB b, int c) :
// if a,b match first scenario:
base(1, 2)
// if a,b match second scenario:
base(3, 4)
// if a,b match third scenario:
base(1, 4)
{
variable = c;
}
};
在这种情况下,构建 derived
实例的辅助函数可能更适合您。
class derived : base{
int variable;
derived(char a, char b, int c) : base(a, b), variable(c) { }
public:
static derived build(int a, int b, int c) {
if(/* a,b match first scenario */) {
return dervied("w", "x", c);
}
else if(/* a,b match second scenario */) {
return dervied("x", "y", c);
}
else if(/* a,b match third scenario */) {
return dervied("1", "2", c);
}
else {
throw std::runtime_error("Bad arguments");
}
}
};
这让您可以在构建 derived
之前分析任何参数,并扩展您的 base
.
最简单的解决方案是通过在传入之前计算参数来将参数传递给基本构造函数。
Derived::Derived(char x, char y, int a) : Base(x , y) {
variable =a;
}
否则我认为您可以定义一个 constexpr 函数,该函数将获取您的 int 值并提供您想要的字符并在 ctor 中调用它。
class base{
base(int arg1, int arg2){/*do something*/}
};
template<auto i>
using val_t=std::jntegral_constant<dedktype(i), i>;
template<auto i>
constexpr val_t<i> val={};
class derived : base{
int variable;
derived(val_t<0>):base(1,2){}
derived(val_t<1>):base(3,4){}
derived(val_t<2>):base(1,4){}
static derived helper(arg a, arg b, arg c){
if (case 1) return derived(val<0>);
if (case 2) return derived(val<1>);
if (case 3) return derived(val<2>);
}
public:
derived(arg a, arg b, arg c) :
derived(helper(a,b,c))
{
variable = c;
}
};
顺便说一句,在您发布 pseudo-code 之前,我无法确定您想要什么。
这里我们使用一个辅助静态函数,它在选择调用哪个构造函数之前可以包含复杂的逻辑。
我们使用不完整的 ctors 来构建我们的基础。
真正的ctor调用helper,然后在helper构建base之后运行它的body。
这使用了 c++11 delegating ctors and constexpr template variables from c++14. It could be done in pure c++11. It also uses guaranteed elision from c++17 没有它你需要一个复制或移动 ctor。
class derived: base{
private:
int variable;
struct args {type1 arg1;type2 arg2;};
static args build ( typeA& a, typeB& b );// make the decision
derived(args&& x, int c)// delegeted only
:base{std::move(x.arg1),std::move(x.arg2)}
,variable(c){};
public:
derived(typeA a, typeB b, int c)// delegating ctor
:derived(build(a,b),c){};
};
我在库中有一个基础 class,出于兼容性原因我不想修改它。这个 class 存储了某些设置,构建后不能修改;构造时必须提供正确的参数。
我自己的代码包含一个从 class 派生的 class。派生class的构造函数的参数结构与基class的构造函数不同;参数不是简单地传递给基础 class 构造函数。
将使用三组预先确定的参数从派生的 class 构造基础 class。使用这三个中的哪一个取决于派生的 class 构造函数的参数。由于成员初始值设定项列表中需要基础 class 参数,因此需要在进入派生构造函数的主体之前做出此决定。
在这种情况下,使用需要为 Arduino (Mega) 编译的代码来完成此操作最优雅的是什么?
演示设置的伪代码:
class base{
base(type1 arg1, type2 arg2){/*do something*/}
};
class derived : base{
int variable;
derived(typeA a, typeB b, int c) :
// if a,b match first scenario:
base(1, 2)
// if a,b match second scenario:
base(3, 4)
// if a,b match third scenario:
base(1, 4)
{
variable = c;
}
};
在这种情况下,构建 derived
实例的辅助函数可能更适合您。
class derived : base{
int variable;
derived(char a, char b, int c) : base(a, b), variable(c) { }
public:
static derived build(int a, int b, int c) {
if(/* a,b match first scenario */) {
return dervied("w", "x", c);
}
else if(/* a,b match second scenario */) {
return dervied("x", "y", c);
}
else if(/* a,b match third scenario */) {
return dervied("1", "2", c);
}
else {
throw std::runtime_error("Bad arguments");
}
}
};
这让您可以在构建 derived
之前分析任何参数,并扩展您的 base
.
最简单的解决方案是通过在传入之前计算参数来将参数传递给基本构造函数。
Derived::Derived(char x, char y, int a) : Base(x , y) {
variable =a;
}
否则我认为您可以定义一个 constexpr 函数,该函数将获取您的 int 值并提供您想要的字符并在 ctor 中调用它。
class base{
base(int arg1, int arg2){/*do something*/}
};
template<auto i>
using val_t=std::jntegral_constant<dedktype(i), i>;
template<auto i>
constexpr val_t<i> val={};
class derived : base{
int variable;
derived(val_t<0>):base(1,2){}
derived(val_t<1>):base(3,4){}
derived(val_t<2>):base(1,4){}
static derived helper(arg a, arg b, arg c){
if (case 1) return derived(val<0>);
if (case 2) return derived(val<1>);
if (case 3) return derived(val<2>);
}
public:
derived(arg a, arg b, arg c) :
derived(helper(a,b,c))
{
variable = c;
}
};
顺便说一句,在您发布 pseudo-code 之前,我无法确定您想要什么。
这里我们使用一个辅助静态函数,它在选择调用哪个构造函数之前可以包含复杂的逻辑。 我们使用不完整的 ctors 来构建我们的基础。
真正的ctor调用helper,然后在helper构建base之后运行它的body。
这使用了 c++11 delegating ctors and constexpr template variables from c++14. It could be done in pure c++11. It also uses guaranteed elision from c++17 没有它你需要一个复制或移动 ctor。
class derived: base{
private:
int variable;
struct args {type1 arg1;type2 arg2;};
static args build ( typeA& a, typeB& b );// make the decision
derived(args&& x, int c)// delegeted only
:base{std::move(x.arg1),std::move(x.arg2)}
,variable(c){};
public:
derived(typeA a, typeB b, int c)// delegating ctor
:derived(build(a,b),c){};
};