0

A recent question on SO made me think about the following.
Consider the following code:

class Base{
 public:
     void print() { cout<<"In Base"<<endl;}
};
class Derived: public Base{
 public:
     void print() { cout<<"In Derived"<<endl;}
};
int main(void)
{
  Base *bp;
  Derived ob;
  bp = &ob;
  (*bp).print();  // prints: In Base
  ob.print();     // print: In Derived 
  return 0;
}

Why does (*bp),print() doesn't behave similar to ob.print().

I think that (*bp) should give back the object ob since bp is referred to object ob and when we de-reference using * operator all that is we get the value at that address and the ob object is stored at the address present in bp. So the first function call should be same as the send one.

Please clarify the concept.

Maroun
  • 94,125
  • 30
  • 188
  • 241
user3144089
  • 91
  • 1
  • 5
  • No clear answer in the link above, I don't think this should be closed on the mentioned duplicate. – Maroun Dec 31 '13 at 08:57
  • @MarounMaroun then clear answer should be provided in the duplicate. But I think this is answered there. – juanchopanza Dec 31 '13 at 08:59
  • 1
    @juanchopanza: The same question in the link made me ask this question as it was unclear to me why de-referencing is yeilding a 'reference` to object instead of giving back the same object. – user3144089 Dec 31 '13 at 09:00
  • So ask that question, instead of repeating the other one. All you are going to get is people telling you to make the method `virtual`. – juanchopanza Dec 31 '13 at 09:01
  • @juanchopanza: You're right. I don't want to see `virtual` as the solution again. – Uchia Itachi Dec 31 '13 at 09:05

5 Answers5

4

What you are doing is called "method hiding", and is a code smell, a bad habit, something one should not do.

You should define your print method as virtual in the base class. (And also don't forget the virtual destructor in the Base class.)

class Base{
 public:
     virtual void print() { cout<<"In Base"<<endl;}
     virtual ~Base(){}
};
class Derived: public Base{
 public:
     void print() { cout<<"In Derived"<<endl;}
};
Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
2

Did you miss to declare function print() virtual? ;)

class Base{
 public:
     virtual void print() { cout<<"In Base"<<endl;}
};
Digital_Reality
  • 4,488
  • 1
  • 29
  • 31
1

Always the decision is based on the pointer type rather than the pointer contents. The former binding is called Early Binding where as the latter is the Late Binding.

If we redefine the method print() preceded with virtual keyword the result will be as required.

class Base
{
 public:
      virtual void print() 
      { 
       cout<<"In Base"<<endl;
      }
 };

class Derived: public Base
{
 public:
      void print() 
      { 
       cout<<"In Derived"<<endl;
      }
};

When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function. Virtual functions ensure that the correct function is called for an object, regardless of the expression used to make the function call.

When calling a function using pointers or references, the following rules apply:

  • A call to a virtual function is resolved according to the underlying type of object for which it is called.
  • A call to a non-virtual function is resolved according to the type of the pointer or reference

You can go through concepts of Virtual Tables and Virtual functions for more details

TryinHard
  • 4,078
  • 3
  • 28
  • 54
0

The compiler uses static types of variables. Variable bp has static type Base * so the compiler checks whether there is such a function in the class definition of Base and calls it. The effect you want to achieve can be done using a virtual function. In this case the compiler calls the function using the table of pointers to virtual functions. In this case as bp has dynamic type Derived * then the table will contain pointer to the virtual function defined in class Derived. All you need to do is to add function specifier virtual to the function definition in class Base

class Base{
 public:
     virtual void print() { cout<<"In Base"<<endl;}
     virtual ~Base() = default};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Base could have plenty of derived classes. At the moment of (*bp).print() you don't know which one of them (if any) is real class of underlying object. So all compiler can do is to call Base::print.

But if you include some information about actual class (vtable) then it's possible to do the way you want (using virtual functions, as suggested by others).

Artem Sobolev
  • 5,891
  • 1
  • 22
  • 40