C ++中复制对象的动态绑定

时间:2012-07-30 08:47:49

标签: c++ virtual-functions dynamic-binding

虚拟功能有问题: 以下是一些代码示例:

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;
       }

结果:              打印()              B ::打印()              Ç::打印()              A ::打印()

我知道这是一个多态,并且知道有一个名为virtual-function-table的表,但我不知道它是如何实现的,并且

   a=b;
   a.print();

结果是:A :: print()不是B :: print(),为什么它没有多态性。 谢谢!

6 个答案:

答案 0 :(得分:5)

对象a仍为类型 A。该作业仅复制b的数据,而不会使a成为B个对象。

这称为object slicing

答案 1 :(得分:2)

a=b;
a.print();

它将打印A::print(),因为a=b会导致对象切片,这意味着a只会获得b a-subobject 。阅读本文:

请注意,运行时多态性可以通过指针引用类型实现 。在上面的代码中,a既不是指针,也不是引用类型:

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)

答案 2 :(得分:1)

因为a不是指针。它是A的一个实例,作业a=b; 将<{1}}的实例复制b。但是函数调用是在a

的实例上

答案 3 :(得分:1)

执行a = b;时,b对象被切片,即仅复制A部分。多态性只能通过指针和引用来实现。搜索“对象切片”以了解该主题。

答案 4 :(得分:0)

要了解有关虚拟方法表的更多信息,请参阅wiki。但在一般情况下,表保留信息方法的地址。因此,表中的A类将有一条记录表示方法 print 位于地址X中。当您执行 pa =&amp; b B类时,只需将表替换为一个方法 print 的地址将指向地址Y。

但是当你执行 a = b 时,你会复制对象。在这种情况下,多态不起作用。

答案 5 :(得分:0)

A类型的对象上调用任何成员函数后,您仍然拥有A个对象(除了显式的析构函数调用,它根本不留下任何内容)

 a = b;

类实例的赋值只是对名为“operator=”的特定成员函数的调用。这里没有“operator=”的特殊之处,除了它的名称是标准的。您可以使用其他名称进行分配:

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

就像您可以写add(a,b)而不是a+b一样,但a+b更具可读性。

对函数的显式调用永远不会更改调用它的变量的类型:

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

声明的a类型为A,不能更改为其他内容:这是a的不变量。

对于指针也是如此:指向A的类型指针的变量将始终具有指向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

但是p可能指向B类型的对象,因此,在运行时,*p的动态类型将为B;但动态类型p始终为A*