在构造函数中调用方法

发布于 2024-10-15 18:59:13 字数 1184 浏览 4 评论 0原文

Herb Sutter 在他的一篇 http://www.gotw.ca 文章中提到构造了一个对象(具有有效的仅当构造函数执行completes.ie时,以粗略的方式将其控制超出其最后的大括号。

现在考虑下面的代码

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

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

}; 

int main()
{
   A a;
}

现在根据 Herb 的说法,我们不能说,由于 A 尚未在其构造函数内完全构造,因此在构造函数内调用 f() 是无效的,因为“this”ptr 尚未准备好。

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

我不认为赫伯说了什么不正确的事情……但我猜我的解释不正确……有人可以向我解释一下那到底是什么吗?

以下是文章的链接: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.

Herb Sutter mentions in one of his http://www.gotw.ca articles that an object is constructed(has valid existence) only if the constructor executes completes.ie to put it in a crude way control passes beyond its final brace.

Now consider the following code

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

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

}; 

int main()
{
   A a;
}

Now from what Herb says, can't we say that since A is not completely constructed inside its constructor Calling f() inside the constructor is invalid as the "this" ptr is not ready yet.

Still there is indeed a valid "this" inside the constructor and f() does get called.

I don't think Herb is saying something incorrect... but guess i am interpreting it incorrectly....can some explain to me what exactly that is?

Here is the link to the article : http://www.gotw.ca/gotw/066.htm
It talks about exceptions from constructors. Specifically here is the extract from it on which my question is based:

-When does an object's lifetime begin?
When its constructor completes successfully and returns normally. That is, control reaches the end of the constructor body or an earlier return statement.

-When does an object's lifetime end?
When its destructor begins. That is, control reaches the beginning of the destructor body.
Important point here is that the state of the object before its lifetime begins is exactly the same as after its lifetime ends -- there is no object, period. This observation brings us to the key question:

We might summarize the C++ constructor model as follows:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅笑依然 2024-10-22 18:59:13

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

仅当 f()class A 或其继承层次结构的 virtual 方法并且您期望 f 的运行时解析时才会出现这种情况() 根据正确的对象。简而言之,如果在构造函数内调用该方法,则虚拟机制不会启动。

如果 f() 不是虚函数,那么只要您知道 f() 到底做什么,从构造函数调用它就没有什么坏处。程序员通常从构造函数调用类方法,例如initialize()

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

Now from what Herb says, can't we say
that since A is not completely
constructed inside its constructor
Calling f() inside the constructor is
invalid as the "this" ptr is not ready
yet.

That is only when f() is a virtual method of class A or its inheritance hierarchy and you expect the runtime resolution for f() according to the right object. In simple words, virtual mechanism doesn't kick in if the method is invoked inside constructor.

If f() is not a virtual function, there is no harm in calling it from constructor(s) provided you know what exactly f() does. Programmers usually call class methods like initialize() from constructor(s).

Can you give me the link to the Herb Sutter's article?

鸢与 2024-10-22 18:59:13

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

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

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

By the time program flow enters your constructor, the object's memory has been allocated and the this pointer is indeed valid.

What Herb means, is that the object's state may not have entirely initialized. In particular, if you are constructing a class derived from A, then that class' constructor will not have been called while you are still inside A's constructor.

This is important if you have virtual member functions, since any virtual function in the derived class will not be run if called from within A's constructor.

夜雨飘雪 2024-10-22 18:59:13

注意:使用确切的文章会更容易,这样我们就可以了解一些背景

生命周期的考虑实际上相当复杂。

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

  • 外部:即对象的使用者
  • 内部:即你在编写构造函数和析构函数时(值得注意的是)

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

  • 开始一旦构造函数成功完成,
  • 析构函数开始运行时就会结束

这意味着如果您尝试在构造过程中或析构过程中访问对象,就会发生坏事(tm)。这主要与多线程程序相关,但如果您将指向对象的指针传递给基类,则可能会发生...这会导致...

...内部观点。情况更复杂。您可以确定的一件事是,所需的内存已被分配,但是对象的某些部分可能尚未完全初始化(毕竟,您正在构造它)。

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

Note: it would have been easier with the exact article, so that we could have some context

Lifetime considerations are actually pretty complicated.

Considering the constructor of an object, there are two different point of views:

  • external: ie the user of an object
  • internal: ie, you when writing constructors and destructors (notably)

From the external point of view, the lifetime of an object:

  • begins once the constructor successfully completed
  • ends when the destructor begins to run

It means that if you attempt to access an object mid-construction or mid-destruction Bad Things Happen (tm). This is mostly relevant to multi-threaded programs, but may happen if you pass pointers to your object to base classes... which leads to...

...the internal point of view. It's more complicated. One thing you are sure of is that the required memory has been allocated, however parts of the objects may not be fully initialized yet (after all, you are constructing it).

  • in the body of the constructor, you can use the attributes and bases of the class (they are initialized), and call functions normally (virtual calls should be avoided).
  • if it's a base class, the derived object is not initialized yet (thus the restriction on virtual calls)
靑春怀旧 2024-10-22 18:59:13

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

The implication from the lifetime not having started yet is mainly that, should the constructor throw an exception, the destructor will not be run.

你丑哭了我 2024-10-22 18:59:13

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

Beware of member variables that are not yet initialized. Beware of virtual functions: the function that you call might not be the one that you expect if the function is virtual and a derived object is created. Other than that, I do not see any problem calling methods from the constructor. Especially the memory for the object has already been allocated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文