Dynamic binding in C++ on copied object

2019-09-01 13:58发布

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!

6条回答
老娘就宠你
2楼-- · 2019-09-01 14:39

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.

查看更多
Root(大扎)
3楼-- · 2019-09-01 14:41

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.

查看更多
迷人小祖宗
4楼-- · 2019-09-01 14:49
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)
查看更多
女痞
5楼-- · 2019-09-01 14:49

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.

查看更多
贪生不怕死
6楼-- · 2019-09-01 14:57

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.

查看更多
老娘就宠你
7楼-- · 2019-09-01 15:00

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*.

查看更多
登录 后发表回答