C++ C++;从父函数调用子函数

C++ C++;从父函数调用子函数,c++,class,C++,Class,我试图从父函数调用一个重写函数,结果发现它只是崩溃了 这很难描述,因此这里是最小可复制代码: #包括 甲级 { 公众: () { init1(); } void init1() { printf(“1”); init2(); printf(“2”); } 虚拟void init2()=0; }; B类:公共A { 公众: B() :A() {} void init2()重写 { printf(“你好”); } }; int main() { B B; 返回0; } 在MSVC 2019上,它崩

我试图从父函数调用一个重写函数,结果发现它只是崩溃了

这很难描述,因此这里是最小可复制代码:

#包括
甲级
{
公众:
()
{
init1();
}
void init1()
{
printf(“1”);
init2();
printf(“2”);
}
虚拟void init2()=0;
};
B类:公共A
{
公众:
B()
:A()
{}
void init2()重写
{
printf(“你好”);
}
};
int main()
{
B B;
返回0;
}
在MSVC 2019上,它崩溃了,它输出“1”,然后
main()
返回0,但我们从未看到
“hello”
“2”

  • 为什么会崩溃?从低层次的角度看会发生什么?
    A
    是否正在尝试调用自己的
    init2()

  • 有没有办法做到这一点,这样我就不必在每个派生类的构造函数中添加
    init2()


  • 不能从基类构造函数(或析构函数)中调用派生类的重写方法。对象的派生类部分尚不存在

    因此,要回答您的问题:

  • A::A()
    正在尝试调用
    A::init2()
    ,而不是
    B::init2()
    ,因此调用纯虚拟方法时崩溃

  • 基类构造函数调用派生类方法有多种方法(如via),但这样做有其局限性(即,无法访问任何派生类数据成员,因为它们仍然不存在,只能访问基类数据成员)。在您的示例中,
    B::init2()
    不访问任何
    B
    数据成员,因此
    A::A()
    可以调用
    B::init2()
    ,但一般来说,您确实需要等待
    B
    开始/完成自身构造,然后才能安全地调用
    B::init2()


  • 调用
    init1()时会出现问题A
    的构造函数中执行code>。在构造函数和析构函数期间调用虚拟函数是危险的,因为最完全派生的类实际上没有处于有效状态--
    a
    的构造函数必须在执行
    B
    之前完全完成,但是对于
    init2(),必须有一个
    B
    表示任何含义。只有在类
    B
    的实例出现之前,才能调用
    init2
    ,因为只有类
    B
    具有
    init2
    的实现。因此,从类
    A
    的构造函数调用
    init2
    是不可能的。我已经阅读了发送的每个链接。有趣的是,我找不到任何与我自己的话。我发现很难描述,结果很糟糕。那么,我想我的问题1已经得到了回答,你有关于2)的一些信息吗?@Nox有一个“工厂”,它通过构造类
    B
    的实例,然后对它们调用
    init2
    。不要让“局外人”访问这些函数(通过将它们设置为
    受保护的
    私有的
    )。要回答你的2),你需要实现另一个
    init
    函数,并在构建对象后调用该函数。我为2添加了一个答案)好的,我明白,很遗憾,它与我正在做的事情不起作用。我将坚持在派生类中调用。没关系。谢谢你抽出时间!