Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何调用未完全构造对象的函数?_C++_Constructor - Fatal编程技术网

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;
}