[英]Is there a way to late-initialize a member variable (a class) in C++?
我来自Java背景。 我有以下程序。
#include <string>
#include <iostream>
class First {
public:
First(int someVal): a(someVal) {
}
int a;
};
class Second {
public:
First first;
Second() { // The other option would be to add default value as ": first(0)"
first = First(123);
}
};
int main()
{
Second second;
std::cout << "hello" << second.first.a << std::endl;
}
在课堂Second
,我想变first
保持未初始化,直到我特别是在初始化Second()'s constructor
。 有办法吗? 或者我只剩下2个选项?:
我不能初始化first
在初始化列表与正确的价值,因为一些操作后得到的值。 因此, first
的实际所需值仅在Second()
构造函数中可用。
我的建议:使用功能:
private: static int calculate_first(int input) {return input*5;}
explicit Second(int input) : first(calculate_first(input)) {}
基类将按照它们在类继承列表中声明的顺序进行初始化,然后成员将按照它们在类中列出的顺序进行初始化,因此计算可以依赖于非静态成员变量和基数如果已经初始化了类。
默认构造函数,然后重新分配:
explicit Second(int input) : first(0) { first = input*5; }
虚拟价值,然后重新分配:
boost::optional<First> first;
explicit Second(int input) { first = input*5; }
使用boost :: optional:
std::unique_ptr<First> first;
explicit Second(int input) { first.reset(new First(input*5));}
Second(const Second& r) first(new First(*(r->first))) {}
Second& operator=(const Second& r) {first.reset(new First(*(r->first)));}
使用堆:
This is tricky and not suggested
and worse in every way than boost::optional
So sample deliberately missing.
But it is an option.
新位置:
This is tricky and not suggested and worse in every way than boost::optional So sample deliberately missing. But it is an option.
first
在成员初始化列表中初始化。
在辅助函数中执行计算并使用转发构造函数可能会有所帮助:
class Second {
public:
Second() : Second(helper_function()) {}
private:
Second(int calc): first(calc) {}
static int helper_function() { return ...; }
First first;
};
你可以在评论中做你所说的,或者,你可以先做一个指向First的指针并随时给它内存,虽然我不推荐这种方式
分离对象生存期的一种方法是使用堆, first
一个指针并在任何时候初始化它:
class Second {
public:
First* first;
Second() {
first = new First(123);
}
};
当然,你可能想要使用某种智能指针而不是原始指针。
这句话是问题的核心:
我无法在初始化列表中首先使用正确的值初始化,因为该值是在某些操作之后获得的。
你应该知道你想要做的事情也不是Java中完美的编程风格 。 保留具有某个默认值的字段,然后在完成某些计算后稍后分配它有效地防止它成为final
,从而使类不可变。
在任何情况下,您的目标必须是使用私有帮助函数 (可能是静态的)将这些计算直接推送到成员的初始化中:
class Second {
private:
First first;
static int getInitializationData()
{
// complicated calculations go here...
return result_of_calculations;
}
public:
Second() : first(getInitializationData()) {}
};
在我看来,其他一切只是一种解决方法,从长远来看会使你的生活复杂化。
如果您不编写显式初始化成员变量的代码,则使用默认初始值设定项对其进行初始化。
C ++标准草案具有以下关于基类和成员变量的初始化:
12.6初始化[class.init]
1如果没有为(可能是cv限定的)类类型(或其数组)的对象指定初始化程序,或初始化程序具有表单(),则按8.5中的指定初始化对象。
和
12.6.1显式初始化[class.expl.init]
1可以使用带括号的表达式列表初始化类类型的对象,其中表达式列表被解释为被调用以初始化对象的构造函数的参数列表。 或者,可以使用=初始化形式将单个赋值表达式指定为初始化程序。 直接初始化语义或复制初始化语义都适用; 见8.5。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.