2017-12-21 11 views
4

매우 이상한 동작을 나타내는 코드를 만들고 있습니다. 나는 코드입니다 다음, 간단한 안녕 세계 스타일의 프로그램에서 복제 관리 : myCallback이 뭔가를 호출 될 때마다가상 상속없는 이상한 동작

#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; 
} 

테스트해야합니다. 그리고이 표시되어야 출력입니다 :

1) ConfigurableTest::SetUp 
2) registerCallback 
3) readyReceiver 
1) ConfigurableTest::SetUp 
2) registerCallback 

당신이 ConfigurableTest::onReady을 볼 수 있듯이 : 나는 Test 클래스에 대한 virtual 상속을 지정하지 않는 한,

1) ConfigurableTest::SetUp 
2) registerCallback 
3) readyReceiver 
4) ConfigurableTest::onReady 

는하지만, 이것은 내가 볼 출력은 실제로는 ConfigurableTest::SetUp이 두 번 호출됩니다!

이 동작의 출처는 무엇입니까? virtual 상속을 사용하지 않고 코드를 다시 작성하여 올바른 동작을 재현하려면 어떻게해야합니까?

+0

어떤 컴파일러를 사용 했습니까? 어쨌든'g ++. exe (Rev1, MSYS2 프로젝트에 의해 빌드 됨) 7.2.0' –

+0

'-std = C++ 11'로 컴파일 된 @underscore_d'g ++ 5.4.0' – Nick

+0

또한' C++ 11' (코드를 약간 변경). – Nick

답변