#include <ctime>
#include <iostream>
using namespace std;

/*
 * ݳԱĻ
 */
struct CBaseClass1
{
    CBaseClass1( size_t i ) : m_val( i ) {}

    size_t m_val;
};
/*
 * ̳ϵ
 */
struct CSubClassV1 : public virtual CBaseClass1
{
    CSubClassV1( size_t i ) : CBaseClass1( i ) {}
};

struct CSubClassV2 : public virtual CBaseClass1
{
    CSubClassV2( size_t i ) : CBaseClass1( i ) {}
};

struct CDiamondClass1 : public CSubClassV1, public CSubClassV2
{
    CDiamondClass1( size_t i ) : CBaseClass1( i ), CSubClassV1( i ), CSubClassV2( i ) {}
};

struct CDiamondSubClass1 : public CDiamondClass1
{
    CDiamondSubClass1( size_t i ) : CBaseClass1( i ), CDiamondClass1( i ) {}
};
/*
 * ̳ϵ
 */
struct CSubClassN1 : public CBaseClass1
{
    CSubClassN1( size_t i ) : CBaseClass1( i ) {}
};
struct CSubClassN2 : public CBaseClass1
{
    CSubClassN2( size_t i ) : CBaseClass1( i ) {}
};
struct CMultiClass1 : public CSubClassN1, public CSubClassN2
{
    CMultiClass1( size_t i ) : CSubClassN1( i ), CSubClassN2( i ) {}
};
struct CMultiSubClass1 : public CMultiClass1
{
    CMultiSubClass1( size_t i ) : CMultiClass1( i ) {}
};
/*
 * ݳԱĽӿڻ
 */
struct CBaseClass2
{
    virtual void func() {};
    virtual ~CBaseClass2() {}
};
/*
 * ̳ϵ
 */
// struct CBaseClassX { CBaseClassX() {i1 = i2 = 0xFFFFFFFF;} size_t i1, i2;};
struct CSubClassV3 : public virtual CBaseClass2
{
};
struct CSubClassV4 : public virtual CBaseClass2
{
};
struct CDiamondClass2 : public CSubClassV3, public CSubClassV4
{
};
struct CDiamondSubClass2 : public CDiamondClass2
{
};

/*
 * ̳ϵ
 */
struct CSubClassN3 : public CBaseClass2
{
};
struct CSubClassN4 : public CBaseClass2
{
};
struct CMultiClass2 : public CSubClassN3, public CSubClassN4
{
};
struct CMultiSubClass2 : public CMultiClass2
{
};

/*
 * ڴ沼.
 */
struct CLayoutBase1
{
    CLayoutBase1() : m_val1( 0 ), m_val2( 1 ) {}

    size_t m_val1, m_val2;
};
struct CLayoutBase2
{
    CLayoutBase2() : m_val1( 3 ) {}

    size_t m_val1;
};
struct CLayoutSubClass1 : public virtual CBaseClass1, public CLayoutBase1, public CLayoutBase2
{
    CLayoutSubClass1() : CBaseClass1( 2 ) {}
};


#define MAX_TEST_COUNT 1000 * 1000 * 16
#define TIME_ELAPSE() ( clock() - start * 1.0 ) / CLOCKS_PER_SEC

int main( int argc, char *argv[] )
{
    /*
     * ϵеĳߴ.
     */
    cout << "================================ sizeof ================================" << endl;
    cout << "    ----------------------------------------------------------------" << endl;
    cout << "sizeof( CBaseClass1 )       = " << sizeof( CBaseClass1 ) << endl;
    cout << endl;
    cout << "sizeof( CSubClassV1 )       = " << sizeof( CSubClassV1 ) << endl;
    cout << "sizeof( CSubClassV2 )       = " << sizeof( CSubClassV2 ) << endl;
    cout << "sizeof( CDiamondClass1 )    = " << sizeof( CDiamondClass1 ) << endl;
    cout << "sizeof( CDiamondSubClass1 ) = " << sizeof( CDiamondSubClass1 ) << endl;
    cout << endl;
    cout << "sizeof( CSubClassN1 )       = " << sizeof( CSubClassN1 ) << endl;
    cout << "sizeof( CSubClassN2 )       = " << sizeof( CSubClassN2 ) << endl;
    cout << "sizeof( CMultiClass1 )      = " << sizeof( CMultiClass1 ) << endl;
    cout << "sizeof( CMultiSubClass1 )   = " << sizeof( CMultiSubClass1 ) << endl;

    cout << "    ----------------------------------------------------------------" << endl;
    cout << "sizeof( CBaseClass2 )       = " << sizeof( CBaseClass2 ) << endl;
    cout << endl;
    cout << "sizeof( CSubClassV3 )       = " << sizeof( CSubClassV3 ) << endl;
    cout << "sizeof( CSubClassV4 )       = " << sizeof( CSubClassV4 ) << endl;
    cout << "sizeof( CDiamondClass2 )    = " << sizeof( CDiamondClass2 ) << endl;
    cout << "sizeof( CDiamondSubClass2 ) = " << sizeof( CDiamondSubClass2 ) << endl;
    cout << endl;
    cout << "sizeof( CSubClassN3 )       = " << sizeof( CSubClassN3 ) << endl;
    cout << "sizeof( CSubClassN4 )       = " << sizeof( CSubClassN4 ) << endl;
    cout << "sizeof( CMultiClass2 )      = " << sizeof( CMultiClass2 ) << endl;
    cout << "sizeof( CMultiSubClass2 )   = " << sizeof( CMultiSubClass2 ) << endl;
    /*
     * ڴ沼
     */
    cout << "================================ layout ================================" << endl;
    cout << "    --------------------------------MI------------------------------" << endl;
    CLayoutSubClass1 *lsc = new CLayoutSubClass1;
    cout << "sizeof( CLayoutSubClass1 )   = " << sizeof( CLayoutSubClass1 ) << endl;
    cout << "CLayoutBase1 offset of CLayoutSubClass1 is " << (char*)(CLayoutBase1 *)lsc - (char*)lsc << endl;
    cout << "CBaseClass1  offset of CLayoutSubClass1 is " << (char*)(CBaseClass1  *)lsc - (char*)lsc << endl;
    cout << "CLayoutBase2 offset of CLayoutSubClass1 is " << (char*)(CLayoutBase2 *)lsc - (char*)lsc << endl;

    int *ptr = (int*)lsc;
    cout << "vbc in CLayoutSubClass1 is " << *(int*)ptr[3] << endl;

    delete lsc;

    cout << "    --------------------------------SI------------------------------" << endl;
    CSubClassV1 *scv1 = new CSubClassV1( 1 );
    cout << "sizeof( CSubClassV1 )   = " << sizeof( CSubClassV1 ) << endl;
    cout << "CBaseClass1 offset of CSubClassV1 is " << (char*)(CBaseClass1 *)scv1 - (char*)scv1 << endl;

    ptr = (int*)scv1;
    cout << "vbc in CSubClassV1 is " << *(int*)ptr[0] << endl;

    delete scv1;

    /*
     * ܲ
     */
    cout << "================================ Performance ================================" << endl;
    double times[4];
    size_t idx = 0;

    CSubClassV1 *ptr1 = new CDiamondClass1( 1 );
    clock_t start = clock();
    {
        for ( size_t i = 0; i < MAX_TEST_COUNT; ++i )
            ptr1->m_val = i;
    }
    times[idx++] = TIME_ELAPSE();
    delete static_cast<CDiamondClass1*>( ptr1 );

    CSubClassN1 *ptr2 = new CMultiClass1( 0 );
    start = clock();
    {
        for ( size_t i = 0; i < MAX_TEST_COUNT; ++i )
            ptr2->m_val = i;
    }
    times[idx++] = TIME_ELAPSE();
    delete static_cast<CMultiClass1*>( ptr2 );

    cout << "CSubClassV1::ptr1->m_val " << times[0] << " s" << endl;
    cout << "CSubClassN1::ptr2->m_val " << times[1] << " s" << endl;

    return 0; 
}


/*
    1. ̳ļָԵ̳ĳߴ4ֽڣ
    2. LayoutԿӶ󱻷˶βƫΪ16vbc
       ָĽӶǰ棬vbcָָΪƫ - 4
    3. VC8ƫƷ麯УΪַֺƫƣƫò
       intʾĸֵ
    4. Կ̳ͨϵָͬͨʳԱʱʱһһ
       µ4ңϻļеĻİš

*/
