2012-07-30 82 views
0

上结合我在虚拟功能的问题: 下面是一些代码作为一个例子:动态在C++中复制的对象

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

结果: A ::打印() B ::打印( ) ç::打印() A :: print()函数

我知道这是一个多态性,并且知道有人称表的虚函数表,但我不知道它是如何实现的,

a=b; 
    a.print(); 

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

回答

2
a=b; 
a.print(); 

它将打印A::print()因为a=b原因对象的切片,这意味着a仅获取A-子对象的b。阅读:

注意,运行时的多态性可以通过指针参考类型来实现。在上面的代码,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) 
+1

非常感谢! – 2012-07-31 03:24:18

5

目的a仍然类型A的。该作业仅从b复制数据,它不会使a a B对象。

这叫做object slicing

+0

非常感谢! – 2012-07-31 03:23:46

1

因为a不是指针。它是A的一个实例,并且转让a=b;拷贝ba的实例。但函数调用在A的实例上。

+0

非常感谢! – 2012-07-31 03:23:53

1

当你做a = b;b对象被切片,即只有A部分被复制。多态仅适用于指针和引用。搜索“对象切片”以了解该主题。

+0

非常感谢! – 2012-07-31 03:24:06

0

要了解更多关于虚拟方法表,请参阅wiki。但通常情况下,表格会保留信息方法的地址。因此,表格中的A类将有一条记录,表示方法打印位于地址X.当您执行pa = & b B类只需将表格替换为其中的一个,以便方法打印的地址将指向地址Y.

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

+0

非常感谢! – 2012-07-31 03:24:49

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*