C++ 如何调用未完全构造对象的函数?
使用构造函数创建对象,以及正在构造的对象的调用函数:C++ 如何调用未完全构造对象的函数?,c++,constructor,C++,Constructor,使用构造函数创建对象,以及正在构造的对象的调用函数: class A { public: A() { this->show(); } void show() { cout<<"show called!"; } }; 我的疑问是,当我使用构造函数创建一个对象时,当对象未完全构造时,我如何能够调用对象函数 虚拟函数调用: class A {
class A
{
public:
A()
{
this->show();
}
void show()
{
cout<<"show called!";
}
};
我的疑问是,当我使用构造函数创建一个对象时,当对象未完全构造时,我如何能够调用对象函数
虚拟函数调用:
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;
}
A类
{
公众:
()
{
}
虚拟虚空显示()
{
cout您正在部分构造的对象中调用函数,如果该函数处理类成员等,则可能会导致错误行为。我不确定它是否调用未定义的行为,但我认为这不是一个好的做法。继承和虚拟函数的情况会变得更糟
在您的示例中,show可以声明为静态,调用它不会有任何风险。将类视为两个独立的部分:包含字段(变量)的对象和方法(函数)。给定类的方法独立于任何特定实例而存在,因此可以在任何时候由有效实例调用,即使是中间构造
这些字段是在对象实例化时,在构造函数运行之前“创建”的。但是,它们没有设置任何值。因此,如果构造函数在字段初始化为合理值之前调用任何方法,那么您将遇到一些未定义的行为
只要可能,如果必须在构造函数中调用方法,请确保将尽可能多的字段初始化为合理值。此代码完全合法。您可以调用方法
在类构造函数中
所有常量(来自初始化列表)都已初始化,并且调用了所有基类构造函数
但是,您不应该在构造函数中调用虚拟方法。请参阅此限制的说明。需要考虑的是,在调用show()时构造了对象的哪些部分
由于从构造函数的主体中(而不是从构造函数的初始值设定项列表中)调用show(),所以可以确信对象的所有成员变量都已构造(因为这发生在构造函数主体执行之前)
如果show()是一个虚拟方法,并且a::a()是从a的子类的构造函数调用的,那么可能会使您出错。在这种情况下,您可能希望show()调用B::show(),但这不会发生,因为B的vtable尚未设置(您将改为调用a::show(),或者在a::show()时导致程序崩溃)(这是一种纯粹的虚拟方法)
我的疑问是,当我使用构造函数创建一个对象时,当对象未完全构造时,我如何能够调用对象函数
在您的示例中,只要您在应该初始化的位置(初始化列表)初始化,就可以了。您正在对已初始化成员的对象使用静态分派(具体地说,A
没有要初始化的此类变量)
那么什么是无效的呢
- 未正确初始化您的成员,或在真正初始化成员之前未使用它们。请不要使用
this
,而使用初始化列表
- 使用构造函数主体(或初始值设定项)中的动态分派。对象未完全构造
- 不寻常的是,您还可以尝试从构造函数将其类型转换为子类
可以调用虚拟函数和非静态成员函数:
见第12.7节:
可以调用4个成员函数,包括虚拟函数(10.3)
施工或破坏期间(12.6.2)
但是,在构造函数中使用虚函数时有一些限制。这有点过分:
当一个虚函数直接或间接地从
构造函数(包括mem初始值设定项或
非静态数据成员的大括号或相等初始值设定项)或
析构函数,调用应用到的对象是
在构造或销毁中,调用的函数是
在构造函数或析构函数自己的类或其
基,但不是在从
构造函数或析构函数的类,或在
最派生对象的其他基类(1.8)
我将上面的段落解释为调用的虚拟函数不会在任何派生类中。这是有意义的,因为在执行阶段的这一点上,派生类中的任何构造函数都不会开始执行
此外,第1部分对非静态成员的使用应在构造开始后进行进行限制。在您的示例中,成员在构造开始后被调用,因此您没有违反第1部分:
对于具有非平凡构造函数的对象,引用
构造函数之前的对象的非静态成员或基类
开始执行会导致未定义的行为
这不是未定义的行为,除非您开始访问未初始化的成员变量,等等。注意对标准的引用。在列表A上,提示我该看哪里。我恐怕还没有像C一样对C++标准进行太多的研究,也就是说,构造函数调用成员是一种常见的模式;对象已经完全初始化,除了FO。r无论构造函数实际要进行什么初始化,请参阅@sashang的答案以获得显式引用检查此代码是否正常:class A{public:A(){}virtual void show(){cout@teacher现在修改代码,从A()中调用show()Scott Meyers写道:“在构造或销毁过程中不应该调用虚拟函数,因为c
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;
}