In C++, is this method call static binding or dynamic binding?
Asked Answered
M

3

6

Here is the class definition:

class Shape { public:
    virtual void draw() = 0; ...
};
class Circle : public Shape {
    public:
        void draw() { ... }
... };
class Rectangle : public Shape { public:
    void draw() { ... } ...
};
class Square : public Rectangle {
    public:
        void draw() { ... }
... };

And here is the client code:

Square* sq = new Square; 
Rectangle* rect = new Rectangle; 
Shape* ptr_shape;
ptr_shape = sq;
ptr_shape->draw();
rect->draw();

A book that I was reading said the last statement is static binding:

enter image description here

However, the statement still looks dynamic binding to me because rect->draw should be called by the pointer in the "vtable" of rect in run-time.

Does anyone have ideas about whether the rect->draw is static binding or dynamic binding?

Mitrailleuse answered 13/1, 2016 at 11:51 Comment(0)
T
8

Rect::draw() is not final and rect is a pointer, so it uses dynamic binding.

But the compiler may use de-virtualization as optimization if all variables are in local scope and all types are known.

Tuition answered 13/1, 2016 at 11:53 Comment(7)
final would prevent it from compiling. It forbids overriding rather than stops it.Piton
@DmitryRubanovich: As final method cannot be overridden (so assuming no Square::draw), as optimization, compiler may call the final method without using the vtable.Tuition
the compiler doesn't call anything. It generates the code which (metaphorically) makes the calls. A compiler cannot generate the code in a subclass which overrides a final method in a super class. A compiler must generate a compile-time error if it encounters such code. Generating code which would ignore the virtual-ness of a function would mean breaking the declaration. In other words, it would not be a compiler optimization. It would be a compiler bug.Piton
Let's say A is pure virtual base class (with virtual f() declared), B and C derive from A. B::f() is final, while C::f() is not. Now let's say D derives from C,B. Based on the order, D's f() is the one which comes from C. Now let's say f() gets called on an instance of D through a pointer of type B. If the virtual-ness of f() was stripped away, it would call B::f(). While it should be calling C::f() based on the declaration. It would be a compiler bug.Piton
@DmitryRubanovich: I mean, in case like that, the (first) call can be devirtualized.Tuition
@DmitryRubanovich: Not sure what you mean for your example, but Demo result if B::fTuition
You are right. I expected the derivation to happen in the listed order and to hide the colliding function names. But the compiler is treating the colliding names as ambiguous except for the situations where they are not ambiguous (so no collision occurs).Piton
B
1

You're overall understanding of the vtable is correct.

I think what the book is trying to say is that the compiler might, and generally will, optimise the rect->draw to be called without going to the vtable.

In this case, the compiler can see that the rect is pointing to a Rectangle object.

In most production code, this will rarely be the case.

Bromleigh answered 13/1, 2016 at 12:5 Comment(0)
P
0

It depends in where. Outside of the code of the class, this will always be dynamic binding. During object construction though (inside of any of the constructors up the chain of inheritance) virtual table lookup is suspended because children-class objects may not have been initialized yet.

Piton answered 13/1, 2016 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.