I can't understand why the following code fails with a purvirt call and calls 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();
}
}
The registration to the Tick
event is the faulting line which for some reason is considered as a pure virtual call to I-don't-know-what.
I played around with this example and noticed a few things:
This only happens if the Base class is pure virtual (notice the
Foo() = 0
)
It doesn't matter if Base::Tick
is private \ public \ protected
etc...
I can (obviously) call OnTick()
from Base
constructor and it works
Anyone got an explanation?
C++/CX is just a compiler wrapper to make COM objects easy. This means objects implementing IUnknown. In the constructor of Base
, the virtual function table for IUnknown
has yet to be initialized, so all entrys are "pure virtual". When you attempt to register the tick handler, it wants to add a reference to this
by calling IUnknown::AddRef
which until the object is fully constructed still points to the "pure virtual" implementation.