2010-03-27 67 views
6

我想运行一个程序的1,000次迭代,所以在main中设置一个1000的计数器。我需要在每次迭代之后重新初始化各种变量,并且由于类构造函数已经写出了所有初始化 - 我决定在每次迭代之后调用它,每次迭代的结果都存储在main变量中。调用构造函数重新初始化变量似乎不起作用?

但是,当我调用构造函数时,它没有任何作用......我花了一段时间才弄清楚 - 但它并没有重新初始化任何东西!

我创建了一个完全像构造函数一样的函数 - 所以对象会有自己的版本。当我打电话时,它会按我的预期重新初始化一切。

int main() 
{ 
Class MyClass() 

int counter = 0; 

while (counter < 1000) 
{ stuff happens } 

Class(); // This is how I tried to call the constructor initially. 
      // After doing some reading here, I tried: 
      // Class::Class(); 
      // - but that didn't work either 
/* Later I used... 
MyClass.function_like_my_constructor; // this worked perfectly 
*/ 
} 

...可能有人试图解释什么,我做错了,或者没有工作,或者是愚蠢的或你有什么?我的意思是 - 从心理上讲,我只是想 - 废话,我可以调用这个构造函数,并重新初始化所有这些东西。构造函数(理想情况下)只有在创建对象时才调用?

+0

*放置新*似乎是可能的。 http://stackoverflow.com/questions/6868363/how-to-recall-a-constructor-of-an-initialised-object – Eonil 2013-07-17 22:42:58

+0

'MyClass = Class();'? – 2015-06-05 20:53:21

回答

8

您的行Class();确实会调用类Class的构造函数,但它会调用它来创建“临时对象”。由于您不使用该临时对象,因此该行没有任何有用的效果。

临时对象(通常)会在它们出现的表达式的末尾消失。它们对于作为函数参数传递或初始化其他对象很有用。仅在声明中创建一个几乎没有用处。该语言允许它作为一个有效的表达式,这只是对于大多数类而言它并没有太大的作用。

C++没有办法在已经构建的对象上调用构造函数。 C++对象的生命周期是一个构造,一个是破坏。这就是它的工作原理。如果你想在它的生命中重置一个对象,你已经做了正确的事情,即调用一个函数来重置它。根据你的班级,你可能不需要编写一个 - 默认的赋值操作符可能完全符合你的需要。这时候,一个临时可以派上用场:

Class myObject; 
// ... do some stuff to myObject ... 

myObject = Class(); 

这将更新myObject从新鲜建造临时的值。它不一定是最有效的代码,因为它会创建一个临时的,然后复制,然后销毁临时的,而不是只将字段设置为其初始值。但除非你的班级规模庞大,否则千次不可能会花费大量时间。

另一种选择是只用一个全新的对象每次迭代:

int main() { 
    int counter = 0; 
    while (counter < 1000) { 
     Class myObject; 
     // stuff happens, each iteration has a brand new object 
    } 
} 

注意Class MyClass();定义类型类的一个对象,叫MyClass的,并且不带参数构造它。它声明一个名为MyClass的函数,它不接受任何参数,并返回一个Class类型的对象。推测在你的真实代码中,构造函数有一个或多个参数。

+0

我使用构造函数,但我很少传递参数,尽管我知道我可以。大多数时候我只是觉得我应该在源代码中的构造函数中设置它们。为什么通过main传递参数呢? – Azoreo 2010-03-27 21:11:08

+0

在这种情况下,如果您没有使用构造函数参数,而且也没有为无参数构造函数使用正确的语法,那么我对您的代码编译感到非常惊讶。无论如何,使用构造函数参数的原因是,如果你的类的对象不完全相同。以标准库为例,您可以指定矢量的初始大小和内容等等。 – 2010-03-27 21:19:11

+0

使用Microsoft Visual Studio C++及其内置的编译器...如果我将构造函数声明为KnightsTour :: KnightsTour(例如),然后放入KnightsTour;在我的头文件中,它会抛出错误,说它看起来像一个函数,但没有参数。 Soooo ...我添加了一个空的参数列表,即“KnightsTour :: KnightsTour()”,然后是“KnightsTour();”在头文件中 - 编译并运行! – Azoreo 2010-03-27 21:30:36

1

是的,这不是典型的用法。创建一个重置变量的函数,并在需要时调用该方法。

0

你陷入了对C++常见的误读。新的C++ 0x使事情变得更清晰。

问题是结构语法看起来像一个函数调用。

void foo(int i) { } 
class Foo { }; 

Foo(10); // construct a temporary object of type foo 
foo(10); // call function foo 
Foo{10}; // construct a temporary object of type foo in c++0x syntax 

我认为C++ 0x语法更清晰。

你可以用这个语法做你想做的事。但要小心它是非常先进的,你应该不是做到这一点。

MyClass.~Class(); // destruct MyClass 
new(&MyClass) Class; 
+0

不这样做的主要原因是,如果'Class'的构造函数抛出,那么对象'MyClass'处于不一致的状态。堆栈展开将尝试再次破坏它,产生未定义的行为。那么,它不会为你写出一个写得很好的'operator ='或'reset'成员函数。所以如果你控制'MyClass'就没有必要这么做了,如果你不控制'MyClass',那么它就会有问题;-) – 2010-03-27 21:22:52

5

在该行的阅读,会发生什么......

Class(); 

是你做实际上调用构造函数 - 为正在从头建立一个临时的对象,然后将其立即销毁因为你没有做任何事情。这非常类似于转换为Class,它使用构造函数调用创建一个值,除了在这种情况下没有值转换以便使用默认构造函数。

编译器可能会暂时优化这个暂停,所以根本没有构造函数 - 我不确定是否允许这样做。

如果你想重新初始化成员,调用构造函数是不行的。将所有初始化代码移动到另一个方法中,并从构造函数中调用该方法,而当您想要重新初始化时,则需要调用该方法。

+2

“我不确定是否允许这样做” - 这是,但是只有当构造函数和析构函数都不影响程序的可观察行为时。因此,如果您在追踪中查看它们是否被省略,那么它们不能被省略。 – 2010-03-27 20:52:12

0

有了这样的要求,我通常会写一个clear()(公共)方法。我从构造函数,析构函数中调用它。用户代码可以随时调用它。

class Foo 
{ 
    public: 

    Foo() { clear(); } 

    ~Foo() { clear(); } 

    void clear(); // (re)initialize the private members 

    private: 

    // private members 
}; 

要在这里回答这个问题,每当它需要重新初始化类,因为它只是初步建设后是clear()方法可以被调用。

相关问题