struct A {
  int a;
  virtual void print() {}

struct B : A {
  int b;
  virtual void print() {}

int main(void)
  A *a = new B;
  a[0].print(); // g++, vs2010, clang call B::print.

The 3 g++, vs2010, clang call B::print. Almost questioning my C++ 101. I had been of the opinion that utilizing a us dot by having an object doesn't create a dynamic dispatch. Only -> having a pointer and us dot having a reference can lead to an engaged dispatch.

So my real question is whether this code is portable?

a[0] is equivalent to *a, which expression is really a reference for an A, and virtual dispatch happens through references just like it will through pointers. a->print() and (*a).print() are entirely identical.

It's portable. a[] returns a reference, and references use dynamic dispatch too.

Yes. It is the same as -


It's portable and also the behavior is well-defined. operator[] on the pointer just does pointer arithmetic along with a dereference. It's adding 0 * sizeof(A) towards the pointer, so in this way it's a "harmful" operation every other value but would fail (on a range of Baloney), but as * sizeof(A) is , within this situation you are ok since it is adding .

Polymorphism creates references in addition to pointers.

Using a[0] having a pointer is well defined and means just like *(a + 0). That's the way the built-in [] operator works.

You're partially right concerning the compiler not requiring to make use of dynamic dispatch when there's no polymorphism. Case a typical optimisation though, and never needed through the language.

Once the code is

A a;

the compiler can call the right function directly, since it will easily notice the item type at compile time.