在构造函数中调用方法
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
仅当
f()
是class A
或其继承层次结构的virtual
方法并且您期望f 的运行时解析时才会出现这种情况()
根据正确的对象。简而言之,如果在构造函数内调用该方法,则虚拟机制不会启动。如果
f()
不是虚函数,那么只要您知道f()
到底做什么,从构造函数调用它就没有什么坏处。程序员通常从构造函数调用类方法,例如initialize()
。你能给我 Herb Sutter 文章的链接吗?
That is only when
f()
is avirtual
method ofclass A
or its inheritance hierarchy and you expect the runtime resolution forf()
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 exactlyf()
does. Programmers usually call class methods likeinitialize()
from constructor(s).Can you give me the link to the Herb Sutter's article?
当程序流进入构造函数时,对象的内存已被分配,并且
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.
注意:使用确切的文章会更容易,这样我们就可以了解一些背景
生命周期的考虑实际上相当复杂。
考虑对象的构造函数,有两种不同的观点:
从外部的角度来看,对象的生命周期:
这意味着如果您尝试在构造过程中或析构过程中访问对象,就会发生坏事(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:
From the external point of view, the lifetime of an object:
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).
生命周期尚未开始的含义主要是,如果构造函数抛出异常,则析构函数将不会运行。
The implication from the lifetime not having started yet is mainly that, should the constructor throw an exception, the destructor will not be run.
当心尚未初始化的成员变量。请注意虚函数:如果函数是虚函数并且创建了派生对象,则您调用的函数可能不是您期望的函数。除此之外,我没有看到从构造函数调用方法有任何问题。特别是对象的内存已经被分配了。
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.