C++ 在构造函数中调用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4872707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling a Method in Constructor
提问by Arun
Herb Sutter mentions in one of his http://www.gotw.caarticles 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.
Herb Sutter 在他的一篇http://www.gotw.ca文章中提到,只有当构造函数执行 completes.ie 以一种粗略的方式将控制传递到其最后的大括号之外时,对象才会被构造(具有有效存在)。
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.
现在从 Herb 所说,我们不能说因为 A 没有在其构造函数中完全构造在构造函数中调用 f() 是无效的,因为“this”ptr 还没有准备好。
Still there is indeed a valid "this" inside the constructor and f() does get called.
在构造函数中仍然确实有一个有效的“this”,并且 f() 确实被调用了。
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?
我不认为 Herb 说的是不正确的……但我猜我的解释不正确……有人可以向我解释那到底是什么吗?
Here is the link to the article : http://www.gotw.ca/gotw/066.htmIt talks about exceptions from constructors. Specifically here is the extract from it on which my question is based:
这是文章的链接:http: //www.gotw.ca/gotw/066.htm它讨论了构造函数的异常。具体来说,这里是我的问题所基于的摘录:
-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.
- 对象的生命周期何时开始? 当它的构造函数成功完成并正常返回时。也就是说,控制到达构造函数体的末尾或更早的 return 语句。
-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:
- 对象的生命周期何时结束?当它的析构函数开始时。也就是说,控制到达析构函数体的开头。 这里的重点是对象在其生命周期开始之前的状态与其生命周期结束后完全相同——没有对象, period。这一观察使我们想到了一个关键问题:
We might summarize the C++ constructor model as follows:
我们可以将 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.
回答by Nawaz
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.
现在从 Herb 所说,我们不能说因为 A 没有在其构造函数中完全构造在构造函数中调用 f() 是无效的,因为“this”ptr 还没有准备好。
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.
只有当f()
是一个virtual
方法class A
或其继承层次结构并且您期望f()
根据正确的对象进行运行时解析时。简而言之,virtual
如果在构造函数内部调用该方法,则机制不会启动。
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).
如果f()
不是虚函数,那么从构造函数调用它没有什么坏处,前提是您知道它到底是f()
做什么的。程序员通常initialize()
从构造函数中调用类方法。
Can you give me the link to the Herb Sutter's article?
你能给我 Herb Sutter 文章的链接吗?
回答by Daniel Gehriger
By the time program flow enters your constructor, the object's memory has been allocated and the this
pointer is indeed valid.
到程序流进入构造函数时,对象的内存已经分配,this
指针确实有效。
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.
Herb 的意思是,对象的状态可能尚未完全初始化。特别是,如果您正在构造一个派生自 的类A
,那么当您仍在 A 的构造函数中时,将不会调用该类的构造函数。
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.
如果您有虚成员函数,这一点很重要,因为如果从 A 的构造函数中调用,派生类中的任何虚函数都不会运行。
回答by Matthieu M.
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...
这意味着,如果您尝试在构建中或破坏中访问对象,则会发生 Bad Things Happen (tm)。这主要与多线程程序有关,但是如果您将指向对象的指针传递给基类,则可能会发生这种情况……这会导致……
...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)
- 在构造函数的主体中,您可以使用类的属性和基类(它们已初始化),并正常调用函数(应避免虚拟调用)。
- 如果它是基类,则派生对象尚未初始化(因此限制了虚拟调用)
回答by Simon Richter
The implication from the lifetime not having started yet is mainly that, should the constructor throw an exception, the destructor will not be run.
生命周期尚未开始的含义主要是,如果构造函数抛出异常,析构函数将不会运行。
回答by Oswald
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.
注意尚未初始化的成员变量。当心虚函数:如果函数是虚函数并且创建了派生对象,则您调用的函数可能不是您期望的函数。除此之外,我没有看到从构造函数调用方法的任何问题。特别是对象的内存已经分配。