基本构造函数中的 C++/CX 委托因纯虚拟调用断言而失败

C++/CX Delegate in base constructor fails with pure virtual call assertion

我无法理解为什么以下代码因 purvirt 调用而失败并调用 abort();

This is a WinRT project using C++/CX

namespace Test {
    public delegate void TickHandle();

    ref class Clock {
    public:
        event TickHandle^ Tick;
    };


    ref class Base {
    internal:
        Base() :
            m_clock(ref new Clock())
        {
            std::cout << "Base::Base" << std::endl;
            m_clock->Tick += ref new Test::TickHandle(this, &Test::Base::OnTick);
            OnTick();
        }
    protected:
        virtual void Foo() = 0;

    private:
        Clock^ m_clock;

        void OnTick()
        {
            std::cout << "Tick" << std::endl;
        }
    };

    ref class Derive : public Base{
    internal:
        Derive() 
        {
            std::cout << "Derive::Derive" << std::endl;
        }
    protected:
        void Foo() override
        {
            std::cout << "Derive::Foo" << std::endl;
        }
    };

    void main()
    {
        auto y = ref new Test::Derive();
    }
}

Tick 事件的注册是故障线,出于某种原因,它被认为是对“我不知道”的纯虚拟调用。

我试用了这个示例并注意到了一些事情:

  1. 这只有在 Base class 是纯虚拟的情况下才会发生(注意 Foo() = 0)

  2. 无所谓Base::Tick是private\public\protected 等...

  3. 我可以(显然)从 Base 构造函数调用 OnTick() 并且它有效

有人得到解释吗?

C++/CX 只是制作 COM objects easy. This means objects implementing IUnknown 的编译器包装器。在Base的构造函数中,IUnknown的虚函数table还没有初始化,所以所有入口都是"pure virtual"。当您尝试注册 tick 处理程序时,它希望通过调用 IUnknown::AddRef 添加对 this 的引用,直到对象完全构建仍然指向 "pure virtual" 实现。