如何在 C++ 中分配 const 成员变量之前验证它的初始化
How to validate the initialization of a const member variable before assigning it in C++
假设我有一个带有 const int 成员变量的简单 class:
class MyClass{
public:
Myclass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) :importantNumber{x}
{
this->anotherNumber = y;
}
由于int importantNumber
是const,我只能在构造函数创建对象时设置它(使用成员初始化列表,如上所示)。
现在,问题是:在实际创建具有该值的 importantNumber 之前,我怎么可能添加对给定构造函数的参数 x 的验证?是否可以创建一个 static int MyClass::validation(int a)
并在构造函数的成员初始化列表中使用它,如 importantNumber{validation(x)}
?
即使可行,还有更好的方法吗?
你加就行了
MyClass::MyClass(int x, int y) : importantNumber{validate(x)}
{
this->anotherNumber = y;
}
int validate(int original)
函数现在可以 return 除了 x
之外的其他东西,或者抛出异常或 assert
或者要求用户确认,无论你认为合适。 =16=]
如果这只是一个简单的检查并且您不想编写 validate
函数,您可以使用 lambda:
MyClass::MyClass(int x, int y) :importantNumber{
[](int number){
assert(number > 0);
return number;
}(x)}
{
this->anotherNumber = y;
}
不过,如果你做得过头了,这可能会有点令人费解。
使用工厂函数创建 class 而不是构造函数。
class MyClass
{
public:
static MyClass* create (int x, int y);
private:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass* MyClass::create (int x, int y)
{
return x > 0 ? new MyClass(x, y) : NULL;
}
当您需要对参数进行一些高级验证时,工厂具有以下优势:
- 如果测试失败,他们会避免在内存中创建对象
- 他们在检查初始化参数方面有更大的灵活性
名单
- 如果您不需要异常也不希望为您的 [= 提供一些“.is_valid()”成员函数,您可以 return NULL 26=].
如果你想用一个简单的条件来验证,你可以在构造函数中使用三元运算符condition ? true : false
:
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(x > 0 ? x : 0)
{
this->anotherNumber = y;
}
但是,请注意,如果您过度使用此运算符,事情很快就会变得难以阅读。
对于更复杂的事情,你可以这样做:
int validateIntegral(int x) const
{
// Do validation on 'x'...
return x;
}
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(validateIntegral(x))
{
this->anotherNumber = y;
}
假设我有一个带有 const int 成员变量的简单 class:
class MyClass{
public:
Myclass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) :importantNumber{x}
{
this->anotherNumber = y;
}
由于int importantNumber
是const,我只能在构造函数创建对象时设置它(使用成员初始化列表,如上所示)。
现在,问题是:在实际创建具有该值的 importantNumber 之前,我怎么可能添加对给定构造函数的参数 x 的验证?是否可以创建一个 static int MyClass::validation(int a)
并在构造函数的成员初始化列表中使用它,如 importantNumber{validation(x)}
?
即使可行,还有更好的方法吗?
你加就行了
MyClass::MyClass(int x, int y) : importantNumber{validate(x)}
{
this->anotherNumber = y;
}
int validate(int original)
函数现在可以 return 除了 x
之外的其他东西,或者抛出异常或 assert
或者要求用户确认,无论你认为合适。 =16=]
如果这只是一个简单的检查并且您不想编写 validate
函数,您可以使用 lambda:
MyClass::MyClass(int x, int y) :importantNumber{
[](int number){
assert(number > 0);
return number;
}(x)}
{
this->anotherNumber = y;
}
不过,如果你做得过头了,这可能会有点令人费解。
使用工厂函数创建 class 而不是构造函数。
class MyClass
{
public:
static MyClass* create (int x, int y);
private:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass* MyClass::create (int x, int y)
{
return x > 0 ? new MyClass(x, y) : NULL;
}
当您需要对参数进行一些高级验证时,工厂具有以下优势:
- 如果测试失败,他们会避免在内存中创建对象
- 他们在检查初始化参数方面有更大的灵活性 名单
- 如果您不需要异常也不希望为您的 [= 提供一些“.is_valid()”成员函数,您可以 return NULL 26=].
如果你想用一个简单的条件来验证,你可以在构造函数中使用三元运算符condition ? true : false
:
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(x > 0 ? x : 0)
{
this->anotherNumber = y;
}
但是,请注意,如果您过度使用此运算符,事情很快就会变得难以阅读。
对于更复杂的事情,你可以这样做:
int validateIntegral(int x) const
{
// Do validation on 'x'...
return x;
}
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(validateIntegral(x))
{
this->anotherNumber = y;
}