2

Not that I have a problem but I found weird following fact.

/* Class Shape */
class Shape
{
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};


/* Class Triangle */
class Triangle: public Shape
{
   public:
      Triangle( int a=0, int b=0)
      {
        Shape(a, b); 
      }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};

int main( )
{
   Shape *shape;
   Triangle tri(10,7);


   shape = &tri;
   (*shape).area();



   return 0;
}

What above will be print is: "Parent class area :".

So it seems the compiler does not check the pointer contents? And calls method only based on pointer type? Otherwise it would have seen that *shape is a Triangle object and would have called Triangle version of area isn't it?

ps. I know you can use virtual functions to make it work the way I describe but that't now what I was interested in, just I found this behaviour little bit weird, maybe I am missing something.

  • 1
    Pointer contents are runtime. That is not the job of the compiler. The compiler's job is to check the syntax and convert your program into an object file that can be linked together with a linker. Any form of intelligence like knowing pointer contents and warnings that you might be doing something illegal is an add on. It will only call the triangle version if Shape::area is virtual. – cup Dec 31 '13 at 07:47

3 Answers3

1

You need to mark int area() as virtual in your base class, i.e.

virtual int area()
{
    /*etc*/

That tells the compiler to build up an appropriate function table so the correct area function is called depending on the type to which the pointer is referring.

(Note that in Java, all non-static functions are implicitly virtual.)

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • This doesn't answer OP's question (whatever it is). They claim to understand that making the function virtual fixes the "problem". – juanchopanza Dec 31 '13 at 07:53
  • @ChristopherCreutzig: Yes got to know that de-referencing gives a reference to the original object rather than the object itself. Place where object and reference to it makes the difference,. – Uchia Itachi Dec 31 '13 at 07:55
  • @juanchopanza: yes. well I think my question comes from confusion that as in my code, the function is called based on pointer type not the actual object it refers to - I found this weird. I think it is called early binding now that I look some more further into it (just it seemed a bit weird to me initially) –  Dec 31 '13 at 07:55
  • @Uchialtachi I don’t understand what you mean. `(*shape).area()` invokes `area` on a `Shape&` that references a `Triangle`. It is exactly equivalent to `shape->area()`, which is (for ordinary pointers and properly written smart pointers) just a shorthand notation. – Christopher Creutzig Dec 31 '13 at 07:59
  • @ChristopherCreutzig: I understood and meant the same thing. Seems my phrases weren't clear enough. Never mind. – Uchia Itachi Dec 31 '13 at 08:13
1

This is because you're not really replacing the function, you're just adding another version to the Triangle class. Inside this class it's always possible to call the parent's version like this

Shape::area();

so both versions need to exist in the Triangle class. Because it's a non-virtual function, the compiler just looks at the name of the type to determine what function in the executable should be called (something cryptic like _ZN5Shape4areaEv) and uses that.

brm
  • 3,706
  • 1
  • 14
  • 14
1

Your main() function could be simplified to:

int main()
{
    Triangle tri(10,7);
    tri.Shape::area();
}

class Triangle has two functions with the name int area() (one in the base and one in the derived class) .

int Triangle::area() would be called by default for for objects of class Triangle, since it hides int Shape::area().

By performing that (C-style) cast on the pointer, you're telling your program to call the version from class Shape. Since, as you've stated, there is no virtual member function table () due to int Shape::area() being non-virtual, the Shape version will be called.

This is expected and well-defined behaviour.

Example:

Further reading:

johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • 1
    It seems to be called early binding what is happening in the code. For some reasons I was expecting compiler or run time would look up that `*shape` corresponds to `Triangle` object and call Triangle's method, but that's not apparently the case, and the function which gets called is decided on compile time based on pointer `type`. –  Dec 31 '13 at 09:06