2010-01-26 46 views
0

我有2類:使用指針基類如數組參數

class Base 
{ 
public: 
    virtual int Foo(int n); 
     virtual void Goo() = 0; 
    virtual ~Base() ; 
}; 


class Derived : public Base 
{ 
public: 
    int Add4Bytes; 

     void Goo(); 
    int Foo(int n);  
}; 

int Test(Base* b) 
{ 
    for (int i=0;i<5;++i) 
    { 
     b->Foo(i); 
     ++b; 
    } 
    return 0; 
} 

void Test2(Base arr[]) 
{ 
    for (int i=0;i<5;++i) 
    { 
     arr[i].Foo(i); 
    } 
} 

void main 
{ 

     Base* b = new Derived[5]; 
     Test(b); 
} 

所以,當我打電話測試,第二環路之後有一個存儲器侵權行爲中的異常。

我有2個問題:

  1. 什麼是測試和Test2的函數參數之間的區別? (我把Base變成純粹的抽象類後,Test2不能編譯)。

和更重要的問題

  • 如何防止該異常,並且如何傳遞派生類的陣列以一個函數,假設以獲得基類數組。 (我不知道在編譯時間哪個派生類我要通過函數)
  • ps - 請不要告訴我讀Meyers書,這就是我問這個問題的確切原因。 :)

    由於

    回答

    3

    由於對象切片,數組不能很好地處理多態類型作爲內容。數組元素具有固定的大小,並且如果派生對象的大小大於基數,那麼基礎對象數組實際上不能包含派生對象。

    即使函數參數可能衰減爲指針,對該指針所做的指針算術將基於數組類型的元素大小。

    要處理多態類型的數組,您需要添加另一個間接級別並處理指向對象的數組(或其他容器)。

    我轉身基地變成純抽象類後的Test2不會編譯

    你不能有抽象類型的數組,因爲你不能有抽象類型的實例(僅指針或引用他們)。

    4

    有參數類型之間沒有任何區別,陣列參數在函數聲明調整爲指針。

    雖然可以將指針轉換爲Derived的指針Base,你不能這樣對待的Derived數組爲Base的陣列,它們是沒有關係的類型。這是因爲在Derived的數組中,Base類是Derived的子對象,而不是Base的數組的一部分。當您執行指針運算就好像它是Base數組的一部分時,您會得到未定義的行爲,您可能會構造一個指向Base對象的指針。

    1

    您的Test功能步驟通過Base對象的數組,即步幅爲sizeof(Base),而它需要是sizeof(Derived)。您可能想要聲明它爲:

    int Test(const std::vector<Base*>&);