C++ 如何在C++;建造师?
下面的示例显示了问题的症结所在。我需要初始化类的常量成员。这只能在初始值设定项列表中完成,而不能在构造函数体中完成。如果构造函数的输入无效,也就是说,如果向量大小小于3,我想断言或抛出一个错误C++ 如何在C++;建造师?,c++,validation,c++11,constructor,C++,Validation,C++11,Constructor,下面的示例显示了问题的症结所在。我需要初始化类的常量成员。这只能在初始值设定项列表中完成,而不能在构造函数体中完成。如果构造函数的输入无效,也就是说,如果向量大小小于3,我想断言或抛出一个错误 class A { // In following constructor, how do we make sure if params.size() // is at least 3. A(const std::vector<int>& params): x(params[
class A {
// In following constructor, how do we make sure if params.size()
// is at least 3.
A(const std::vector<int>& params):
x(params[0]), y(params[1]), z(params[2]) {}
private:
const int x;
const int y;
const int z;
};
A类{
//在下面的构造函数中,如何确保params.size()
//至少3岁。
A(常量标准::向量和参数):
x(参数[0]),y(参数[1]),z(参数[2]){}
私人:
常数int x;
const int y;
常量int z;
};
请在现代C++(11和以后)
中实现这一点,只需添加一层抽象即可。您可以编写一个函数,确保向量大小正确,甚至可以确保值在预期范围内(如果有)。那看起来像
class A {
A(const std::vector<int>& params):
x(verify(params, 0)), y(verify(params, 1)), z(verify(params, 3)) {}
private:
static int verify(const std::vector<int>& params, int index)
{
if (params.size() < 4) // or use if (params.size() <= index) if you only care if the index will work
throw something;
return params[index];
}
const int x;
const int y;
const int z;
};
A类{
A(常量标准::向量和参数):
x(验证(参数,0)),y(验证(参数,1)),z(验证(参数,3)){}
私人:
静态int验证(const std::vector¶ms,int index)
{
if(params.size()<4)//或use if(params.size()const
成员只能在构造函数的成员初始化列表中初始化。要验证调用方的输入,必须调用帮助函数来验证每个输入值,然后再将其传递给相应的成员,例如:
int check(const std::vector<int> ¶ms, int index) {
if (params.size() <= index) throw std::length_error("");
return params[index];
}
class A {
A(const std::vector<int>& params):
x(check(params, 0)), y(check(params, 1)), z(check(params, 3)) {}
private:
const int x;
const int y;
const int z;
};
通过转换的其他选项附加层:
class A_params{
friend class A;
int x;
int y;
int z;
void validate();
public:
A_params(std::initializer_list<int>);
A_params(const std::vector<int>&);
A_params(int(&)[3]);
//...
};
class A {
// In following constructor, how do we make sure if params.size()
// is at least 3.
public:
A(A_params params):
x(params.x), y(params.y), z(params.z) {}
private:
const int x;
const int y;
const int z;
};
A类参数{
A级朋友;
int x;
int-y;
intz;
void validate();
公众:
A_参数(标准::初始值设定项列表);
A_参数(const std::vector&);
A_参数(int(&)[3]);
//...
};
甲级{
//在下面的构造函数中,如何确保params.size()
//至少3岁。
公众:
A(A_参数):
x(params.x),y(params.y),z(params.z){}
私人:
常数int x;
const int y;
常量int z;
};
不像其他解决方案那样优雅,但是……您只需在第一个常量的初始化内部的三元运算符中添加一个抛出
class A
{
private:
const int x;
const int y;
const int z;
public:
A (const std::vector<int>& params)
: x{ params.size() < 4u ? throw std::runtime_error{"!"}
: params[0] },
y{params[1]}, z{params[3]}
{ }
};
A类
{
私人:
常数int x;
const int y;
常量int z;
公众:
A(常量标准::向量和参数)
:x{params.size()<4u?throw std::runtime_error{“!”}
:params[0]},
y{params[1]},z{params[3]}
{ }
};
非主题建议:如果A
是类
,那么构造函数最好是public
使用std::at()而不是运算符[]。请注意,const
数据成员有限制。您将无法分配给A
。通常,不变成员会由于类型的接口而保持不变,除了为对象分配一个全新的A
值外,无法对其进行更改。值得注意的是,这是一个非常好的使用ca的方法例如,你应该手头有一个兼容c++20的编译器。我读得对吗?违反这个约束是一个编程错误。为什么要使用std::vector而不是3个参数?@JVApen,同意在这种特殊情况下,使用std::vector没有多大意义。所以,请不要对示例读太多。示例只是为了说明实际问题是如何在初始值设定项列表中使用构造函数参数之前验证它们。size()@RemyLebeau如果大小小于4,则该OP会被具体调用出错。我想我应该使用params.size()<4
来满足这一点。OP说“如果向量大小小于4”以及“如果params.size()至少是3“,所以这有点矛盾。我个人认为4是一个输入错误,索引3应该是2。在xy
和z
值之间存在间隙的情况下,传入4元素向量没有多大意义。3元素向量更有意义。但无论如何,size()@ ReMyLeBeAuo非常正确。至少现在它应该以任何方式显示它们。我认为这是一个解决方案。但是,它看起来像一个黑客。看起来C++没有更具体的方法来验证构造函数参数。我们可以做一些类似的事情来减少它的冗长。X(验证(PARAMS)?PARAM[0 ]:断言(0)),y(PARAMS)[1] ,z(params[2])这只是将验证问题转移到A_params
@FrançoisAndrieux验证不是问题!问题是在成员列表初始化之前执行代码和平。C'est difficile l'anglais non?在实现A_params::A_params(const std::vector&)时也会遇到同样的问题
。这就是我将问题转移到A_params
的意思。是的,l'anglais est parfois difficile:peace=paix et piece=morceau。我想我没有抓住重点。使用成员初始化的目的是因为'A'的成员是常量,如果这是唯一的原因,那么这个答案将在A_params
之后起作用>不需要const
成员。
class A
{
private:
const int x;
const int y;
const int z;
public:
A (const std::vector<int>& params)
: x{ params.size() < 4u ? throw std::runtime_error{"!"}
: params[0] },
y{params[1]}, z{params[3]}
{ }
};