我尋找用於C++對象的局部重新初始化的最佳模式對象。部分重新初始化++通過構造
對於部分重新初始化,我的意思是某些成員(代碼示例中的step_param
)需要保留其值,並且其他成員(代碼示例中的value
)被重新初始化。
重要的一點:應避免執行與構造函數基本相同的init()或reset()成員函數的膨脹和冗餘。
到目前爲止,我有以下解決方案:
namespace reinit_example
{
struct reinit_t {} reinit;
struct stepper_t
{
int step_param; // keep parameter
int value;
stepper_t()
: step_param(1)
, value(step_param)
{}
stepper_t(const stepper_t & c, reinit_t)
: step_param(c.step_param)
, value(step_param)
{}
void step()
{
value += step_param;
}
};
void use_cases_1()
{
stepper_t c;
// use c
c.step();
// and later reinit
c = stepper_t(c,reinit);
}
} // namespace
還應該有繼承和組合工作得很好:
namespace reinit_example
{
struct stepper_2_t : public stepper_t
{
int step_param_2; // keep parameter
int value_2;
public:
stepper_2_t()
: step_param_2(0)
, value_2(step_param_2)
{}
stepper_2_t(const stepper_2_t & cc, reinit_t)
: stepper_t(cc)
, step_param_2(cc.step_param_2)
, value_2(step_param+2)
{}
void step()
{
stepper_t::step();
value_2 += value + step_param_2;
}
};
struct stepper_comp_t
{
stepper_t c;
stepper_2_t cc;
public:
stepper_comp_t()
{}
stepper_comp_t(const stepper_comp_t & d, reinit_t)
: c(d.c,reinit)
, cc(d.cc,reinit)
{}
void step()
{
c.step();
cc.step();
}
};
void use_cases_2()
{
stepper_2_t cc;
// use cc, change config
cc.step();
// maybe change config
cc.step_param = 2;
// reinit
cc = stepper_2_t(cc,reinit);
stepper_comp_t d;
d = stepper_comp_t(d,reinit);
}
} // namespace
C++ 11的非靜態成員初始化使它更簡單:
#if __has_feature(cxx_nonstatic_member_init)
namespace reinit_example
{
struct stepper_11_t
{
int step_param = 0 ; // keep value
int value = step_param;
stepper_11_t()
{}
stepper_11_t(const stepper_11_t & c11, reinit_t)
: step_param(c11.step_param)
{}
};
void use_cases_3()
{
stepper_11_t c11;
c11 = stepper_11_t(c11,reinit);
}
} // namespace
#endif
來進行測試:
傑裏·科芬提出的int main()
{
reinit_example::use_cases_1();
reinit_example::use_cases_2();
#if __has_feature(cxx_nonstatic_member_init)
reinit_example::use_cases_3();
#endif
}
解決方案:參數被移動到一個單獨的結構,它被傳遞到構造函數來重新初始化。
namespace reinit_example
{
struct stepper_config_t
{
struct config_t
{
config_t()
: step_param(1)
{}
int step_param;
int other_param;
};
config_t config;
int value;
stepper_config_t()
: value(config.step_param)
{}
stepper_config_t(const config_t & c)
: config(c)
, value(c.step_param)
{}
void step()
{
value += config.step_param;
}
};
void use_cases_4()
{
stepper_config_t c;
// use c
// and later reinit
c = stepper_config_t(c.config);
}
} // namespace
【什麼問題,你實際上是試圖解決?(http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)這聽起來像一個大量的工作做一些事情,因爲C++對象在其生命週期中僅被初始化(構造)一次,所以它確實沒有什麼意義(「部分重新初始化」?)。 – 2012-01-07 22:01:27
你的回答非常快。你真的想過嗎? – hpc 2012-01-07 22:06:10
這不是一個答案,它是一個評論,要求澄清。是的,我確實考慮過這個問題,並得出這樣的結論:這可能不是解決您嘗試解決的任何問題的正確方法。這就是爲什麼我問你的實際問題是什麼。 [你試圖做X,並且你想到解決方案Y.所以你問的是解決方案Y,甚至沒有提到X.問題是,可能有更好的解決方案,但除非你知道,否則我們無法知道描述X是什麼。](http://www.perlmonks.org/index.pl?node_id=542341) – 2012-01-07 22:07:34