调用构造函数来初始化变量

Call constructor to initialize variables

本文关键字:变量 初始化 构造函数 调用      更新时间:2023-10-16

我在C++中有以下类定义:

class foo {
private:
   int      a,b,c;
   foo();     // constructor
   void     setup(int x, int y);
   void     some_function_that_changes_a_b_c();
}

foo::foo() {
   a = b = c = 0;
}
void foo::setup(int x, int y) {
    foo();    // <-- I use this to make sure a,b,c are initialized
    a = x;
    b = y;    // <-- c is left unchanged!
}
void foo::some_function_that_changes_a_b_c() {
    // here's some code that changes variables a,b,c
}

然后我有一个使用此类的代码:

foo  *a = new foo;
a->setup(1,2);
a->some_function_that_changes_a_b_c();
a->setup(5,7);   // <-- HERE IS THE PROBLEM

问题是在第二次调用 setup() 时,它不会运行 foo() 构造函数来重置我的值或 a,b,c ,因此 c 变量保持调用 some_function_that_changes_a_b_c() 时的旧值,我用调试器对此进行了测试,似乎在第二次调用时, foo() 正在为变量寻址不同的内存空间。

有没有办法解决这个问题?

在C++中,构造函数仅在构造对象时调用一次,不再在类方法中调用。在您的代码中

void foo::setup(int x, int y) {
    foo();  // ==> this line
}

将创建一个临时的 foo 对象,该对象独立于当前this对象,因此this对象的abc字段将保持不变。

为了做你想做的事情,创建一个类方法,比如foo::reset(),然后从foo::setup()内部调用它。

创建对象后,不应调用构造函数。将功能放入从构造函数和setup函数调用的受保护reset()函数中。

背景:调用 foo() in setup 不会重新初始化对象,而是创建第二个从未使用的本地对象。通常,除非你绝对知道自己在做什么,否则你应该避免显式调用构造函数。

foo();    // <-- I use this to make sure a,b,c are initialized

不幸的是,它没有这样做。它创建并销毁临时对象。不能直接调用构造函数;它们仅用于在对象的生命周期开始时初始化对象。

您可以使用新初始化的对象重新分配对象:

*this = foo();

或者,您可以将构造函数的主体移动到 reset 函数中,并在要还原初始状态时调用该函数。

我的首选选项是使用单独的对象,而不是尝试重用修改后的对象,并在初始化每个对象时执行所有"设置":

foo a(1,2);
a.some_function_that_changes_a_b_c();
foo b(5,7);  // known to be in a freshly initialised state

您尝试执行的是两阶段初始化。 这在C++中是不必要的和笨拙的。 你需要意识到两件事

  1. 在对象创建时调用构造函数

  2. 如果你有一个对象要说f.setup(1, 2, 3);,这意味着构造函数必须已经运行。

现在:

foo f; // calls foo() with f
f.setup(1, 2, 3); // foo() has arleady been called

正如熊颖所指出的,foo()线会创建一个与您正在使用的this无关的临时对象。

而不是两阶段初始化(构造函数,然后是初始值设定项),你可以让你的构造函数获取变量并执行初始化

class foo {
  private:
   int      a,b,c;
  public:
   foo(int x, int y, int z);     // constructor
};
foo::foo(int x, int y, int z)
   : a(x),
   b(y),
   c(z)
{ }

然后使用所需的值进行构造

foo f(1, 2, 3);

如果需要在每次调用setup时"重置"值,则最好使用 reset 函数或类似函数。 尝试自己调用构造函数是可能的,但不是很健康。

void foo::reset() {
    a = b = c = 0;
}