Reputation: 6355
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 main(void)
{
C c;
std::cout << ((C::member_offset(c) == 0) ? 0 : 1);
std::cout << std::endl;
std::system("pause");
return 0;
}
The program above outputs 1
. What it does is just check the addresses of the c
object and the c
's field m_x
. It prints out 1
which means the addresses are not equal. My guess is that is because the d'tor is virtual so the compiler has to create a vtable
for the class and put a vpointer
in the class's object. If I'm already wrong please correct me.
Apparently, it puts the vpointer
at the beginning of the object, pushing the m_x
field farther and thus giving it a different address. Is that the case? If so does the standard specify vpointer
's position in the object? According to wiki it's implementation-dependent. And its position may change the output of the program.
So can you always predict the output of this program without specifying the target platform?
Upvotes: 1
Views: 376
Reputation: 129454
In reality, it is NEARLY ALWAYS laid out in this way. However, the C++ standard allows whatever works to be used. And I can imagine several solutions that doesn't REQUIRE the above to be true - although they would perhaps not work well as a real solution.
Note however that you can have more than one vptr/vtable for an object if you have multiple inheritance.
Upvotes: 3
Reputation: 500663
Yes, it is implementation dependent and no, you can't predict the program's output without knowing the target platform/compiler.
Upvotes: 1
Reputation: 477338
There are no "vpointers" in C++. The implementation of polymorphism and dynamic dispatch is left to the compiler, and the resulting class layout is not in any way specified. Certainly an object of polymorphic type will have to carry some extra state in order to identify the concrete type when given only a view of a base subobject.
Implementations with vtables and vptrs are common and popular, and putting the vptr at the beginning of the class means that you don't need any pointer adjustments for single inheritance up and downcasts.
Many C++ compilers follow (parts of) the Itanium ABI for C++, which specifies class layout decisions like this. This popular article may also provide some insights.
Upvotes: 3