在构造函数中调用方法

时间:2011-02-02 09:32:39

标签: c++ object constructor

Herb Sutter在他的http://www.gotw.ca篇文章中提到,只有当构造函数执行完成时才构造一个对象(具有有效存在性)。将它置于粗略的方式控制超出其最终大括号。

现在考虑以下代码

class A
{
  public:
  A() 
  { 
      f();
  }

  void f() 
  { 
      cout << "hello, world"; 
  }

}; 

int main()
{
   A a;
}

现在从Herb所说的,我们不能说因为A在构造函数中没有完全构造,所以在构造函数内部调用f()是无效的,因为“this”ptr还没有准备好。

构造函数中确实存在一个有效的“this”,并且f()会被调用。

我不认为Herb说的不正确......但我猜我正在解释它......可以解释一下究竟是什么原因吗?

以下是该文章的链接:http://www.gotw.ca/gotw/066.htm 它讨论了构造函数的异常。具体来说,这是我的问题所依据的摘录:

- 对象的生命周期何时开始? 当构造函数成功完成并正常返回时。也就是说,控制到达构造函数体的末尾或更早的return语句。

- 对象的生命周期何时结束? 当它的析构函数开始时。也就是说,控制到达析构函数体的开头。 重要的一点是,对象在其生命周期开始之前的状态与其生命周期结束之后的状态完全相同 - 没有对象,句点。这一观察将我们带到了关键问题:

我们可以按如下方式总结C ++构造函数模型:

Either:

(a) The constructor returns normally by reaching its end or a return statement, and the object exists.

Or:

(b) The constructor exits by emitting an exception, and the object not only does not now exist, but never existed.

5 个答案:

答案 0 :(得分:18)

  

现在从赫伯所说的,我们不能说   因为A不完全   在其构造函数内构造   在构造函数中调用f()是   无效,因为“此”ptr尚未就绪   爱好。

仅当f()virtual的{​​{1}}方法或其继承层次结构时,并且您期望根据正确的对象获得class A的运行时解析。简单来说,如果在构造函数中调用该方法,则f()机制不起作用。

如果virtual不是虚函数,那么从构造函数调用它是没有害处的,只要你知道f()究竟是什么。程序员通常从构造函数中调用类f()等类方法。

你能给我链接到Herb Sutter的文章吗?

答案 1 :(得分:8)

当程序流进入构造函数时,对象的内存已经分配,​​this指针确实有效。

Herb的意思是,对象的状态可能没有完全初始化。特别是,如果要构造一个派生自A的类,那么当您仍在A的构造函数中时,将不会调用该类的构造函数。

如果您有虚拟成员函数,这很重要,因为如果从A的构造函数中调用,则派生类中的任何虚函数都不会运行。

答案 2 :(得分:3)

注意:使用确切的文章会更容易,因此我们可以有一些上下文

终身考虑实际上非常复杂。

考虑对象的构造函数,有两种不同的观点:

  • 外部:即对象的用户
  • internal:即你在编写构造函数和析构函数时(特别是)

从外部角度来看,对象的生命周期:

  • 在构造函数成功完成后开始
  • 在析构函数开始运行时结束

这意味着如果您尝试访问构建中期或中期破坏 Bad Things Happen(tm)。这主要与多线程程序有关,但如果将指向对象的指针传递给基类,可能会发生......这会导致......

......内部观点。它更复杂。你确定的一件事是已经分配了所需的内存,但是部分对象可能还没有完全初始化(毕竟,你正在构建它)。

  • 在构造函数的主体中,您可以使用类的属性和基础(它们被初始化),并且通常调用函数(应该避免虚拟调用)。
  • 如果它是基类,派生对象尚未初始化(因此对虚拟调用的限制)

答案 3 :(得分:2)

生命周期尚未开始的含义主要是,如果构造函数抛出异常,析构函数将不会被运行。

答案 4 :(得分:0)

注意尚未初始化的成员变量。注意虚函数:如果函数是虚函数并且创建了派生对象,则调用的函数可能不是您期望的函数。除此之外,我没有看到从构造函数调用方法有任何问题。特别是已经分配了对象的内存。