2012-07-30 64 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*