I’m slightly ashamed to admit that I just made a discovery about C++ classes that I probably should have realised years ago.

If you have something like


class A {
  public:
    virtual void fn() { cout << "I'm A" << endl;} ;
} ;

class B : public A {
  public:
    void fn() { cout << "I'm B" << endl ;} ;
} ;

void callfn(A a){
  a.fn() ;
}

it doesn’t do what I expected at all…

For instance, consider the code

  A a; B b;
  callfn(a) ; callfn(b) ;

This compiles just fine – but the output is


I'm A

I'm A

!!!!

In fact, you need to be using pointers to get the behaviour I was after


void callfn(A *a){
  a->fn() ;
}

 ...

  A a; B b;

  callfn(&a) ; callfn (&b) ;

This exhibits the behaviour I was looking for, namely:


I'm A

I'm B

It’s probably very obvious why this is the case, but it stumped me for a bit.