Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

understanding c++ pointers to parent/base classes

I was asked this interview question and I got it wrong. "What is the output": My answer was 135, the actual output is 136. This implies that the pointer's to the two parent classes are not equal even though they pass the prior test of being equal to the child class. I thought I understood c++ pointers, but this has me stumped for an explanation. Although I think I see what's going on, I'm not sure why. Any c++ experts out there that can offer a technical explanation? It appears the first two comparisons are more logical in nature, while the last comparison is more literal...

#include <iostream>

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

    protected:
    int m_i;
};

class B
{
    public:
    B() : m_d(0.0) { }

    protected:
    double m_d;
};

class C
    : public A, public B
{
    public:
    C() : m_c('a') { }

    private:
    char m_c;
};

int main()
{
    C c;
    A *pa = &c;
    B *pb = &c;

    const int x = (pa == &c) ? 1 : 2;
    const int y = (pb == &c) ? 3 : 4;
    const int z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) ? 5 : 6;

    std::cout << x << y << z << std::endl;
    return 0;
}
like image 880
Gio Avatar asked Apr 06 '16 15:04

Gio


People also ask

Can you derive a pointer from base class?

Explanation: A base class pointer can point to a derived class object, but we can only access base class member or virtual functions using the base class pointer because object slicing happens when a derived class object is assigned to a base class object.

Can pointers reference objects of different base types?

A pointer reference is polymorphic, since it can reference objects of different dynamic type.

What can hold the address of a pointer to the base class?

By default base class pointer can hold the address of base class as well as derived call we all know. But if we don't use virtual keyword in base class then the base class pointer will call methods based on the type of pointer not on based on the value it holding.

What is the difference between base class and parent class?

The Base class members and member functions are inherited to Object of the derived class. A base class is also called parent class or superclass. Derived Class: A class that is created from an existing class. The derived class inherits all members and member functions of a base class.


1 Answers

Perhaps if you print out pa and pb it will be more clear what is going on.

std::cout << "A: " << pa << std::endl;
std::cout << "B: " << pb << std::endl;
std::cout << "C: " << &c << std::endl;

Running this at the end of main gives me

A: 0xbfef54e0
B: 0xbfef54e4
C: 0xbfef54e0

(your output may be different, the important thing is that they aren't all equal)

This is because of how a C object is represented in memory. Since a C is both an A and a B, it needs to have the data members from each part. The real layout of C is something like this (ignoring padding):

int    A::m_i;
double B::m_d;
char   C::m_c;

When you convert a C* to an A*, the compiler knows that the A part starts at offset 0, so the pointer value doesn't change. For C* to B* it needs to offset by sizeof(int) (plus padding). This offset handling is done automatically for you for calculating x and y. For z it is bypassed since you use reinterpret_cast

like image 78
Kevin Avatar answered Sep 28 '22 09:09

Kevin