Click here to Skip to main content
15,884,099 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I was given this code to test my cpp understanding, and I am quite confused:

C++
#include "stdafx.h"
#include <iostream>
#include <cstddef>

using namespace std;

class A
{
public:
    A() : m_x(0) { }

public:
    static ptrdiff_t member_offset(const A &a)
    {
        const char *p = reinterpret_cast<const char*>(&a);
        const char *q = reinterpret_cast<const char*>(&a.m_x);

        return q - p;
    }

private:
    int m_x;
};

class B
    : public A
{
public:
    B() : m_x('a') { }

public:
    static int m_n;

public:
    static ptrdiff_t member_offset(const B &b)
    {
        const char *p = reinterpret_cast<const char*>(&b);
        const char *q = reinterpret_cast<const char*>(&b.m_x);

        return q - p;
    }

private:
    char m_x;
};

int B::m_n = 1;

class C
{
public:
    C() : m_x(0) { }
    virtual ~C() { }

public:
    static ptrdiff_t member_offset(const C &c)
    {
        const char *p = reinterpret_cast<const char*>(&c);
        const char *q = reinterpret_cast<const char*>(&c.m_x);

        return q - p;
    }

private:
    int m_x;
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    B b;
    C c;
    std::cout << ((A::member_offset(a) == 0) ? 0 : 1);
    std::cout << ((B::member_offset(b) == 0) ? 0 : 2);
    std::cout << ((A::member_offset(b) == 0) ? 0 : 3);
    std::cout << ((C::member_offset(c) == 0) ? 0 : 4);
    std::cout << std::endl;

    return 0;
}


Why is the answer 0204?
Posted
Comments
Mohibur Rashid 19-Jan-13 8:00am    
How about debugging? try debugging, you will know
DaveAuld 19-Jan-13 8:00am    
Have you stepped through and watched all the various variables? What about doing it with a pen and paper, step through line by line and write down what you think is happening.

1 solution

On a typical implementation, the answer would be:

Since class A does not have any virtual functions, it will not have any vtable and since it does not derive from another class it first member will start at the same address as the class itself. This will give you the two 0 of your output (0204).

Since class B derives from class A, its members will be placed after those of the parent class in the layout. And since class A is not empty, then the offset will not be 0. It might have been 0 (depending on the compiler) if it was empty. This will give the 2 in your output.

For class C, the vtable could be placed before the data thus the data won't be at offset 0. This will give the 4 in your output.

Most of this is compiler and platform dependant and can vary depending according to selected compiler options (alignment, empty class optimization...)

By the way, you should avoid code that depends on the layout of a class whenever possible as it will not be portable.
 
Share this answer
 
Comments
H.Brydon 19-Jan-13 13:18pm    
Agree with Philippe (+5).

The code also had endian issues too. This adds another mechanism for answers to be different on different platforms.
Sergey Alexandrovich Kryukov 19-Jan-13 22:56pm    
Nice explanation, good advice, a 5.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900