【问题标题】:C++ Call child function from parent [duplicate]C ++从父级调用子函数[重复]
【发布时间】:2021-06-19 15:43:06
【问题描述】:

我正在尝试从父级调用覆盖的函数,但发现它只是崩溃了。

这很难描述,所以这里是最小的可重现代码:

#include <iostream>

class A
{
public:
    A()
    {
        init1();
    }
    
    void init1()
    {
        printf("1");
        init2();
        printf("2");
    }

    virtual void init2() = 0;
};

class B : public A
{
public:
    B()
    : A()
    {}

    void init2() override
    {
        printf("hello");
    }
};

int main()
{
    B b;
    return 0;
}

在 MSVC 2019 上它崩溃了,在 http://cpp.sh/ 上它输出“1”,然后 main() 返回 0,但我们从未看到 "hello""2"

  1. 为什么会崩溃?从低层次的角度会发生什么? A 是否试图调用自己的 init2()

  2. 有没有办法做到这一点,所以我不必在每个派生类中,在其构造函数中添加init2()

【问题讨论】:

  • A 的构造函数中调用init1(); 时出现问题。在构造函数和析构函数期间调用虚函数是危险的,因为最完全派生的类实际上并不处于有效状态——A 的构造函数必须在 B 执行之前完全完成,但你必须有B 表示 init2(); 表示任何意思。
  • 只有类B 的实例才能调用init2,因为只有类B 具有init2 的实现。因此从类A 的构造函数调用init2 是不行的。
  • 我已阅读所有发送的链接。有趣的是,我无法用我自己的话找到任何东西。我发现很难描述并且得到了非常糟糕的结果。好吧,所以我想我的问题 1 已经回答了,请问您对 2) 有什么看法吗?
  • @Nox 有一个“工厂”,它通过构造 B 类的实例,然后在它们上调用 init2。不允许“外人”访问这些功能(将它们设为protectedprivate)。
  • 要回答您的 2),您需要实现另一个 init 函数并在构造对象后的某个时间调用它。

标签: c++ class


【解决方案1】:

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

所以,回答你的问题:

  1. 是的A::A() 正在尝试调用A::init2(),而不是B::init2(),因此调用纯虚方法会崩溃。

  2. 基类构造函数可以通过多种方式(例如通过CRTP)调用派生类方法,但这样做有局限性(即,无法访问任何派生类数据成员,因为它们仍然没有' t 存在,只能访问基类数据成员)。在您的示例中,B::init2() 不访问任何B 数据成员,因此A::A() 可以调用B::init2(),但通常您确实需要等待@987654329 @ 在您可以安全地调用 B::init2() 之前开始/完成构建自身。

【讨论】:

  • 我为 2) 添加了答案
  • 好的,我明白了,不幸的是它不适用于我正在做的事情。我会坚持我在派生类中的调用。没关系。感谢您的宝贵时间!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多