Question

I have a problem in virtual function: Here is some code as an example:

class A
   {
      public : virtual  void print(void)
           {
              cout<< "A::print()"<<endl;
           }
    };
 class B : public A
    {
      public : virtual void print(void)
           {
               cout<<"B::print()"<<endl;
           }
    };
 class C : public A
    {
      public : void print(void)
            {
               cout<<"C::print()"<<endl;
            }
     };
  int main(void)
     {
         A a,*pa,*pb,*pc;
         B b;
         C c;
         pa=&a;
         pb=&b;
         pc=&c;

         pa->print();
         pb->print();
         pc->print();

         a=b;
         a.print();
         return 0;
       }

the result: A::print() B::print() C::print() A::print()

I know it's a Polymorphism ,and know have a table called virtual-function-table,but I don't know how it is to achieve,And

   a=b;
   a.print();

the result is: A::print() not B::print(),why it hasn't polymorphism. thank you!

Was it helpful?

Solution

a=b;
a.print();

It will print A::print() because a=b causes object-slicing, which means a gets only the a-subobject of b. Read this :

Note that runtime-polymorphism can be achieved only through pointer and reference types. In the above code, a is neither pointer, nor reference type:

A * ptr = &b; //syntax : * on LHS, & on RHS
A & ref =  b; //syntax : & on LHS, that is it!

ptr->print(); //will call B::print() (which you've already seen)
ref.print();  //will call B::print() (which you've not seen yet)

OTHER TIPS

The object a is still of type A. The assignment only copies data from b, it doesn't make a a B object.

This is called object slicing.

Because a is not a pointer. It is an instance of A, and the assignment a=b; copies the instance of b to a. But the function call is on an instance of A.

When you do a = b; you b object is sliced i.e. only the A part of it gets copied. Polymorphism only works through pointers and references. Search "object slicing" to learn about the subject.

To learn more about virtual method table please see wiki. But in general case the table keeps the information methods' addresses. So, class A in the table will have one record says that method print is in address X. When you do pa=&b class B simply replace the table to its one in such a way that address of method print will point to address Y.

But when you do a=b you copy object. In this case polymorphism doesn't work.

After a call to any member function on a object of type A, you still have A object (except an explicit destructor call, which leaves nothing at all).

 a = b;

The assignment of a class instance is just a call to a particular member function called "operator=". There is nothing special with "operator=" here, except its name is standard. You could use another name for assignment:

a = b;
// you could as well write:
a.assign(b);
// (if such member was defined)

Just as you could write add(a,b) instead of a+b, but a+b is more readable.

An explicit call to a function never changes the type of the variable it is called on:

A a;
foo(a);
// a is still a A
a.bar();
// a is still a A

The declared type of a is A, and cannot be changed to something else: this is an invariant of a.

This is also true for pointers: a variable of type pointer to A will always have the type pointer to A:

void foo (A*&);
A *bar();

A a;
A *p = &a;
foo (p); // might change p
// a still has type: pointer to A
p = bar();
// a still has type: pointer to A

But p might point to an object of type B, so, at runtime, the dynamic type of *p will be B; but the dynamic type of p is always A*.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top