如何调用未完全构造的对象的函数?
使用构造函数创建一个对象,并调用正在构造的对象的函数:
class A
{
public:
A()
{
this->show();
}
void show()
{
cout<<"show called!";
}
};
现在我在 main() 中创建对象,如下所示:
int main()
{
A a;
int xy;
cin>>xy;
return 0;
}
我的疑问是,当我使用构造函数创建对象时那么当对象没有完全构造时我如何能够调用对象函数呢?
虚拟函数调用:
class A
{
public:
A()
{
}
virtual void show()
{
cout<<"show called!";
}
};
class B:public A
{
public:
B()
{
A *a=this;
a->show();
}
void show()
{
cout<<"derived show";
}
};
int main()
{
A a;
B b;
int xy;
cin>>xy;
return 0;
}
输出正常工作:派生显示
creating an object using a constructor and along with that calling functions of object which is being constructed:
class A
{
public:
A()
{
this->show();
}
void show()
{
cout<<"show called!";
}
};
and now i m creating object in main()
as below:
int main()
{
A a;
int xy;
cin>>xy;
return 0;
}
my doubt is that when i am creating an object using constructor then how i am able to call object function while object is not fully constructed?
virtual function calls:
class A
{
public:
A()
{
}
virtual void show()
{
cout<<"show called!";
}
};
class B:public A
{
public:
B()
{
A *a=this;
a->show();
}
void show()
{
cout<<"derived show";
}
};
int main()
{
A a;
B b;
int xy;
cin>>xy;
return 0;
}
working fine with output: derived show
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
可以调用虚函数和非静态成员函数:
请参阅 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf:
但是,在构造函数中使用虚函数时存在一些限制。有点拗口:
我将上面的段落解释为调用的虚函数不会出现在任何派生类中。这是有道理的,因为此时在执行阶段,派生类中的任何构造函数都不会开始执行。
此外,第 1 部分还规定了非静态成员的使用应在构造开始后进行。在您的示例中,成员在构造开始后被调用,因此您没有违反第 1 部分:
It's fine to call virtual functions and non-static member functions:
See section 12.7 of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf:
However when using virtual functions in a constructor there are some restrictions. It's a bit of a mouthful:
I interpret the above paragraph as saying the virtual functions called will not be in any derived class. This makes sense because at this point in the execution phase any constructor in a derived class will not have begun execution.
Additionally part 1 places a restriction that use of non-static members should occur after the construction begins. In your example the members are being invoked after the construction begins, so you're not violating part 1:
这段代码是完全合法的。您可以调用方法
在类构造函数中。
所有常量(来自初始化列表)都已初始化,并且所有基类构造函数都已调用。
但是,您不应在构造函数中调用虚拟方法。请参阅 Scott Meyers 对此限制的解释。
This code is completely legal. You can call methods
in the class constructor.
All constants (from the initialization list) are already initialized and all base class constructors are called.
However, You should not call virtual methods in the constructor. See Scott Meyers explanation for this restriction.
需要考虑的是,调用 show() 时对象的哪些部分被构造?
由于您从构造函数体内(而不是例如构造函数的初始值设定项列表中)调用 show(),因此您可以放心,A 对象的所有成员变量都已被构造(因为这发生在执行构造函数体之前)。
如果 show() 是一个虚拟方法,并且 A::A() 是从 A 的子类的构造函数中调用的,那么可能会让您陷入困境。在这种情况下,您可能希望 show() 调用 B:: show() ,但这不会发生,因为 B 的 vtable 尚未设置(您最终会调用 A::show() ,或者如果 A::show() 是纯粹的,则程序崩溃-虚拟方法)
The thing to think about is, which parts of the object are constructed at the time when you call show()?
Since you call show() from within your constructor's body (and not e.g. from within the constructor's initializer list) you can rest assured that all of the A object's member variables have already been constructed (since that happens before the constructor body is executed).
What might trip you up would be if show() was a virtual method, and A::A() was being called from the constructor of a subclass of A. In that case, you might want show() to call B::show(), but that won't happen because the vtable for B hasn't been set up yet (you would end up calling A::show() instead, or crashing the program if A::show() was a pure-virtual method)
您正在部分构造的对象中调用函数,如果此类函数处理类成员等,则可能会导致错误的行为。我不确定它是否会调用未定义的行为,但我认为这不是一个好的做法。而继承和虚函数的情况会变得更糟!
在您的示例中,可以将 show 声明为静态,并且调用它不会有任何风险。
You are calling a function in an partially constructed object, which may result in erroneous behavior if such function deals with class members and such. I am not sure whether its invoking undefined behaviour or not, but I don't think its a good practice. And the situation gets worse with inheritance and virtual functions!
In your example, show could be declared static and there will be no risk in calling it.
将类视为两个独立的部分:包含字段(变量)的对象和方法(函数)。给定类的方法独立于任何特定实例而存在,因此可以由有效实例随时调用它,甚至在构造过程中也是如此。
这些字段是在对象实例化时、构造函数运行之前“创建”的。但是,它们没有设置任何值。因此,如果您的构造函数在字段初始化为合理值之前调用任何方法,那么您将遇到一些未定义的行为。
只要有可能,如果必须在构造函数内调用方法,请确保将尽可能多的字段初始化为合理的值。
Consider a class as 2 separate parts: The object containing fields (variables) and the methods (functions). The methods of a given class exist independent of any particular instance, so it can be called at any time by a valid instance, even mid-construction.
The fields are "created" when the object is instantiated, before the constructor is run. However, they have no values set to them. So, if your constructor calls any methods BEFORE the fields are initialised to sensible values, then you're going to experience some undefined behaviour.
Whenever possible, if you must call a method inside a constructor, be sure to initialise as many fields as possible to sensible values.
只要您在应该初始化的位置(初始化列表)进行初始化,您的示例中发生的情况就很好。您正在对已初始化成员的对象使用静态分派(具体来说,
A
没有要初始化的此类变量)。那么什么是无效的呢?
this
。what happens in your example is fine, as long as you initialize where you are supposed to (the initialization list). you are using static dispatch on an object which has initialized members (specifically,
A
has no such variables to initialize).what then is invalid?
this
.