【问题标题】:Derived of template class not calling constructor派生的模板类不调用构造函数
【发布时间】:2021-08-24 05:00:29
【问题描述】:

我正在用 C++ 实现一个事件模板,如下所示

模板.h

template<typename EventArg>
class Event {
public:
    typedef void (*EventHandle)(const EventArg&);
    vector<EventHandle> EventHandles;


protected:
    virtual void Init() { throw EventNotInitialized();};
    Event() 
    {
        printf("Event() \n");
        Init();
    }
};

事件.h

struct E_EventArgs {
    string data;
};
class E_Event : public Event<E_EventArgs>
{
public:
    static E_Event * Get() {
        static auto ins = new E_Event();
        return ins;
    }
protected:
    void Init() override {
        printf("E_Event() Init() \n");
    }
    E_Event() {
        Init();
        printf("E_Event() \n");
    }
};

然后我调用E_Event::Get() 访问E_Event。但这是日志:

Event()

我使用 arm-oe-linux-gnueabi-g++(gcc 版本 6.4.0 (GCC))

为什么E_Event的构造函数没有被调用?

【问题讨论】:

  • 为什么你认为E_Event构造函数没有被调用? (我相信您已经得出了一个毫无根据的结论。)如果您将throw EventNotInitialized(); 替换为printf("Event() Init() \n");,情况可能会更清楚?
  • 在您尝试该实验后,请参阅Calling virtual functions inside constructors
  • 正在调用构造函数。您的问题是——E_Event 的构造函数中调用了哪个版本的Init()?惊讶吗?
  • @JaMiT 你是对的。抛出发生在构造函数调用之前。
  • @Silver 有了这个新见解(E_Event 的构造函数被调用),你能写一个更准确的问题来更好地代表这种情况吗? (强制性免责声明,即使在我看来不太可能:如果编辑此问题会使当前答案无效,则新版本应该是一个新问题。)

标签: c++ templates singleton


【解决方案1】:

您观察到的结果并不是从构造函数调用虚函数的结果。

在构造函数中,虚拟调用机制被禁用,因为尚未发生从派生类的覆盖。对象是从基础向上构建的,“在派生之前的基础”。

这意味着当您从E_Event 的构造函数调用Init() 时,Init() 的最新“最新”覆盖版本属于基类Event

但是,在您的情况下,来自E_Event 的构造函数的Init() 调用不会发生。

在构造派生类时,也会构造基类的实例。 考虑这个简单的例子。

#include <iostream>
class Base
{
public:
    Base()
    {
        std::cout<<"Base constructor"<<std::endl;
    }
};
class Derived: public Base
{
public:
    Derived()
    {
        std::cout<<"Derived constructor";
    }
};
int main()
{
  Derived();
}

输出将是

Base constructor
Derived constructor

如您所见,Base 的构造函数也被调用了。 因此,E_Event 的构造函数也调用了 Event(),这已经引发了异常,这就是为什么 E_Event 中的任何内容都不会被调用。

【讨论】:

  • 不是主要问题。但感谢报价。我还不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-20
  • 1970-01-01
  • 2014-09-23
  • 1970-01-01
  • 2016-07-19
  • 2012-11-06
  • 2018-07-21
相关资源
最近更新 更多