没有虚拟继承的奇怪行为
Odd behavior without virtual inheritance
我正在处理一段表现出非常奇怪行为的代码。我设法在一个简单的 hello world 风格的程序中复制了它,下面是代码:
#include <iostream>
using namespace std;
class Test
{
public:
virtual ~Test() = default;
protected:
virtual void SetUp() { }
};
class ICallbackReceiver
{
public:
virtual ~ICallbackReceiver() = default;
virtual void onReady() = 0;
};
// C-style callback
void readyReceiver(void* userdata)
{
cout << "3) readyReceiver\n";
static_cast<ICallbackReceiver*>(userdata)->onReady();
}
using callback_t = void(*)(void*);
callback_t myCallback;
void* myUserData;
void registerCallback(callback_t callback, void* userData)
{
cout << "2) registerCallback\n";
myCallback = callback;
myUserData = userData;
}
class ConfigurableTest : public /*virtual*/ Test, public ICallbackReceiver
{
public:
void SetUp() override
{
cout << "1) ConfigurableTest::SetUp\n";
registerCallback(&readyReceiver, static_cast<void*>(this));
}
void onReady() override
{
cout << "4) ConfigurableTest::onReady\n";
}
};
int main()
{
ConfigurableTest test;
test.SetUp();
myCallback(myUserData);
return 0;
}
每当调用 myCallback
时,都必须进行测试。这是应该显示的输出:
1) ConfigurableTest::SetUp
2) registerCallback
3) readyReceiver
4) ConfigurableTest::onReady
但是,除非我为 Test
class 指定 virtual
继承,否则这是我看到的输出:
1) ConfigurableTest::SetUp
2) registerCallback
3) readyReceiver
1) ConfigurableTest::SetUp
2) registerCallback
如您所见,ConfigurableTest::onReady
从未被调用,但 ConfigurableTest::SetUp
实际上被调用了两次!
这种行为的起源是什么?如何在不使用 virtual
继承的情况下重构代码以重现正确的行为?
问题是因为您进行了转换 ConfigurableTest
-> void *
-> ICallbackReceiver
,这是不允许的。您需要从 void *
转换回相同的类型 ConfigurableTest
- 在这种情况下没有错误。
另见 multiple inheritance: unexpected result after cast from void * to 2nd base class
我正在处理一段表现出非常奇怪行为的代码。我设法在一个简单的 hello world 风格的程序中复制了它,下面是代码:
#include <iostream>
using namespace std;
class Test
{
public:
virtual ~Test() = default;
protected:
virtual void SetUp() { }
};
class ICallbackReceiver
{
public:
virtual ~ICallbackReceiver() = default;
virtual void onReady() = 0;
};
// C-style callback
void readyReceiver(void* userdata)
{
cout << "3) readyReceiver\n";
static_cast<ICallbackReceiver*>(userdata)->onReady();
}
using callback_t = void(*)(void*);
callback_t myCallback;
void* myUserData;
void registerCallback(callback_t callback, void* userData)
{
cout << "2) registerCallback\n";
myCallback = callback;
myUserData = userData;
}
class ConfigurableTest : public /*virtual*/ Test, public ICallbackReceiver
{
public:
void SetUp() override
{
cout << "1) ConfigurableTest::SetUp\n";
registerCallback(&readyReceiver, static_cast<void*>(this));
}
void onReady() override
{
cout << "4) ConfigurableTest::onReady\n";
}
};
int main()
{
ConfigurableTest test;
test.SetUp();
myCallback(myUserData);
return 0;
}
每当调用 myCallback
时,都必须进行测试。这是应该显示的输出:
1) ConfigurableTest::SetUp
2) registerCallback
3) readyReceiver
4) ConfigurableTest::onReady
但是,除非我为 Test
class 指定 virtual
继承,否则这是我看到的输出:
1) ConfigurableTest::SetUp
2) registerCallback
3) readyReceiver
1) ConfigurableTest::SetUp
2) registerCallback
如您所见,ConfigurableTest::onReady
从未被调用,但 ConfigurableTest::SetUp
实际上被调用了两次!
这种行为的起源是什么?如何在不使用 virtual
继承的情况下重构代码以重现正确的行为?
问题是因为您进行了转换 ConfigurableTest
-> void *
-> ICallbackReceiver
,这是不允许的。您需要从 void *
转换回相同的类型 ConfigurableTest
- 在这种情况下没有错误。
另见 multiple inheritance: unexpected result after cast from void * to 2nd base class