2

I have some code which accesses the derived and base ptrs and when I print out the addresses, they are the same. If this is the case, how does the compiler know whether the address it is referring to is an A or a B?

Here is the code:

#include <iostream>

class A
{
public:
   A() : val_(0) {
       ptrA = this;
   }

   virtual void set(int val) { val_ = val; }

   virtual void printval() = 0;

   static A* ptrA;

   int val_;
};

class B : public A
{
public:
   B() : A() {
      ptrB = this;
   }

   virtual void printval() { std::cout << A::val_ << std::endl; }

   static B* ptrB;
};

A* A::ptrA = 0;
B* B::ptrB = 0;

int main() {

   A* p = new B();
   p->set(3);
   p->printval();

   std::cout << "A part address=" << A::ptrA << std::endl;
   std::cout << "B part address=" << B::ptrB << std::endl;

   return 0;
}

Here is the printout:

A part address=00501F40
B part address=00501F40

Both addresses are exactly the same. Does the compiler also store some extra information?

EDIT: Yes I meant to say how does program know at runtime.

Angus Comber
  • 9,316
  • 14
  • 59
  • 107
  • Do you really mean "how does the compiler know"? Or do you mean "how does the **compiled code** know?"? Basically, are you talking about compile-time or run-time? – Oliver Charlesworth Mar 28 '13 at 18:27
  • 1
    The basic answer to your qustion is "[vtable](http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/)" – paulsm4 Mar 28 '13 at 18:29
  • The *compiler* often **doesn't** know what polymorphic type it's addressing, that's a major attribute of polymorphism. At runtime, the vtable is resolved to point to things the compiler may have had no knowledge of. – ssube Mar 28 '13 at 18:30
  • 1
    @user619818 - Oli Charlesworth and peachykeen are pointing out that there's a difference between "compile time" and "runtime". Runtime polymorphism is expressed via "virtual" methods (a "compile time" thing), and implemented via "vtables" (a "runtime thing"). 'Hope that helps... – paulsm4 Mar 28 '13 at 18:33

2 Answers2

2

The extra information in built-in through an implementation dependent mechanism. When you compile your program the compiler quietly adds all the code that it needs for the bookkeeping.
For almost all compilers the dynamic dispatch is implemented through a virtual table and pointer.

Food Read:

What happens in the hardware when I call a virtual function? How many layers of indirection are there? How much overhead is there?

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • The virtual table is part of the class, while the pointer to the table is a hidden element of the object. You can see the effect of the pointer with `sizeof`. – Mark Ransom Mar 28 '13 at 18:31
  • IIRC, in MSVC, the pointer to the vtable is the first element of the class. The vtable itself is then an array of pointers (keying off of method order). This is used in a decent bit of software to hook virtual calls at runtime. – ssube Mar 28 '13 at 18:32
0

In effect, presuming a “normal” C implementation such as yours, much of the data of class B is a structure, and the first member of that structure is an object of class A. Since both B and the A that it contains start at the same place, they have the same address.

Because there is an A object at the start of B, you can convert a pointer to the B object to a pointer to the A object, and it acts like an A object because it is: It is a pointer to the A data.

Virtual functions are more complicated. Inside the A data, not usually visible to you, is a pointer to a table. If the object were really a plain A object, that pointer would point to a table that has the addresses of the virtual functions for A. If the object is a B object, then that pointer points to a table that has the addresses of the virtual functions for B. The result is that, if you have a pointer whose compile-time type appears to be pointer-to-A, the compiler calls its functions by looking up their addresses in the table. If the actual type of the pointed-to object is B, this table provides the addresses of the virtual functions for B.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312