在构造函数中初始化多个相关const属性的最简单方法
Simplest way to initialize multiple related const properties in a constructor?
当c++类的多个const属性依赖于一些中间计算时,初始化它们的最简单方法是什么?
例如,如何更正下面类的构造函数?
class MyClass {
public:
const int a;
const int b;
MyClass() {
int relatedVariable = rand() % 250;
a = relatedVariable % 100;
b = abs(relatedVariable - 150);
}
};
在c++ 11中,您可以简单地使用委托构造函数:
class MyClass
{
public:
const int a;
const int b;
private:
MyClass( int relatedVariable )
: a( relatedVariable % 100 ),
b( abs( relatedVariable - 150 ) ) {}
public:
MyClass() : MyClass( rand() % 250 ) {}
};
这里有一个使用委托构造函数的迂回解决方案:
class MyClass
{
MyClass(int aa, int bb) : a(aa), b(bb) { }
static MyClass Maker() { int x = /* ... */; return MyClass(x * 2, x * 3); }
int const a;
int const b;
public:
MyClass(MyClass const &) = default;
MyClass() : MyClass(Maker()) { }
};
对于我们这些碰巧喜欢在编码中不那么高级的人来说,这将有点工作:
class MyClass {
public:
int iamStupid; /* K.I.S.S. */
const int a;
const int b;
MyClass()
: iamStupid(rand() % 250)
, a(iamStupid % 150)
, b(abs(iamStupid - 150))
{}
};
额外的成员带来了不必要的开销——对于手头的任务来说可能很重要,也可能不重要。噢,代码很简单。
记住在 a
和b
之前声明iamStupid
!(见注释)
您可以这样做——不漂亮,但应该可以达到目的:
class MyClass {
public:
const int a;
const int b;
static int relatedVariable;
MyClass() :
a(setRand()),
b(relatedVariable) {}
static const int setRand()
{
relatedVariable = rand() % 250;
return relatedVariable;
}
};
int MyClass::relatedVariable = 0;
如果您使用的是不支持委托构造函数的旧编译器,这里有适用于旧语言版本的相同方法:
class MyClassBase {
public:
const int a;
const int b;
MyClassBase(int a, int b) : a(a), b(b) {}
};
class MyClass : public MyClassBase {
static MyClassBase Maker() {
int x = rand() % 250;
return MyClassBase(x % 100, abs(x - 150));
}
public:
using MyClassBase::a;
using MyClassBase::b;
MyClass() : MyClassBase(Maker()) { }
};
引入一个中间类来进行计算:
class ConstCalc {
public:
ConstCalc(int related) : rv(related){}
int a() const { return rv % 100; }
int b() const { return abs( rv - 150 ) ; }
private:
const int rv;
};
class MyClass {
public:
const int a;
const int b;
MyClass( const ConstCalc c ) : a( c.a() ), b( c.b() ) {
}
};
Const是类的用户和实现者之间的契约。它表明类用户不应该修改成员变量,从而提供不可变的对象设计。构造函数可以初始化该状态。也就是说,最好将它们隐藏在私有访问限定符之后,并提供允许只读的访问器。暂时删除const-ness的正确方法是使用const_cast<>。
class MyClass {
public:
const int a;
const int b;
MyClass() : a(0), b(0) {
int relatedVariable = rand() % 250;
const_cast<int&>(a) = relatedVariable % 100;
const_cast<int&>(b) = abs(relatedVariable - 150);
}
};
您可以将a
和b
设置为私有,并提供从类外部访问它们的值的getter。
class MyClass
{
private:
int a, b; // private
public:
int getA() { return a; }
int getB() { return b; }
MyClass()
{
int relatedVariable = rand() % 250;
a = relatedVariable % 100;
b = abs(relatedVariable - 150);
}
};
或者,您可以使用子对象初始化器并以某种方式缓存随机数。打开优化甚至可以删除生成的程序文本中的临时变量。
class MyClass
{
private:
int temp; // this is a workaround
public:
const int a;
const int b;
MyClass() : temp(rand() % 250), a(temp % 100), b(abs(temp - 150)) {}
};
请记住,子对象的构造是按照类中成员声明的顺序进行的,并且忽略初始化列表中子对象的顺序。
或者,您可以偷懒,只存储初始随机数,并根据需要生成a, b
。