Let us try to think in the compiler way
//1 Do I have a matching function in class A1 for this? Yes.
void m1(A1 a) can accept object cc. (Since cc is an instance of class (c1) derived from A1 --> Displays A1
//2 Do I have a matching function in class B1 to accept object cc? Well. Though I don't have on my own, I inherited one function from A1
void m1(A1 a) which can take this argument cc.
//3 Above mentioned holds good here as appropriate to class C1
The point to note here is that compiler always looks for appropriate methods in the type of object it refers to and not the parent class A1..
//4 I have an appropriate function in class A1 to execute this statement.
//5 Above mentioned holds good for class B1
Output:
A1 A1 A1 A1** B1** C1**
Correct me if I am assuming something wrong...