2016-10-07 58 views
0

考慮下面的代碼:衍生**基地**

#include <iostream> 

using namespace std; 

class Base 
{ 
public: 
    int foo; 
}; 

class Derived : public Base 
{ 
public: 
    float bar; 
}; 

int main() 
{ 
    Base** baseArr = new Base*[30]; 

    for (int i=0; i<30; i++) 
    { 
     Derived* derived = new Derived(); 
     derived->foo = i; 
     derived->bar = i * 2.5; 
     baseArr[i] = derived; 
    } 

    //Notice this! 
    Derived** derivedArr = (Derived**)(baseArr); 

    for (int i=0; i<30; i++) 
     cout << "My Base " << i << ": " << derivedArr[i]->foo << ", " << derivedArr[i]->bar << endl; 

    return 0; 
} 

它是安全的這樣做數組的數組類型轉換?整個程序的指針大小是一樣的,所以聽起來好像我不會得到任何填充錯誤。但是,我知道正確的方法是遍歷每個元素並單獨投射。

然而,我試着去利用這種投將我的模板公共職能的實現使用非通用私有函數返回數組.cpp文件,所以我可以肯定,我的Base數組將只包含特定Derived指針。

private: 
    Base** Find(function<bool(Base*)> Predicate, int& N); //Implemented in .CPP 

public: 
    template <class T> T** FindByType(int &N) //T is derived from Base 
    { 
     //Safe? 
     return (T**)(Find(
      [](Base* b)->bool { return typeid(T) == typeid(b); }, 
      N)); 
    }; 

這當然只是一個簡單的例子。在這種情況下,我有很多理由使用RTTI。 N用於控制數組大小。

我想知道如果這個不安全投將與多繼承失敗,例如像Derived類也將繼承OtherBase,我想投給OtherBase**,我也想知道如果任何機會,我到達未定義的行爲,或者我決定使用這種構造時可能遇到的任何潛在問題。

+1

您應該使用標準的[容器](http://en.cppreference.com/w/cpp/container),例如[std :: vector](http://en.cppreference.com/w/cpp/container/vector) –

+0

不,這是不安全的,指針別名說不。 –

+0

@BasileStarynkevitch,你可以安全地施放矢量到矢量沒有for循環? –

回答

1

不,這是不安全的。

如果一個程序試圖通過的其他一個glvalue比以下類型的行爲是未定義的一個訪問對象的存儲值:

  • 動態類型的對象,
  • cv-qualified版本的對象的動態類型,
  • 類型相似(如4.中定義的)。4)動態類型的對象,
  • 一種類型,是有符號或對應的動態對象的類型無符號類型,
  • 在所述簽名或對應於無符號類型的類型CV-合格版本的動態對象的類型的,
  • 的聚集體或聯合類型包括其元件或非靜態數據成員(包括遞歸中上述類型的一個,一個元件或非靜態數據成員的亞集團或包含的聯盟),
  • 這是一種類型(可能是cv合格的)基礎c lass類型的物體的動態類型,
  • a charunsigned char類型。

Ben

沒有這些案件無恥被盜是在鑄造Base**Derived**的情況屬實。

2

不,它不安全。

指向Derived的指針與指向Base的指針不同。指向Derived的指針可以轉換爲指向Base的指針,但最終結果是不同的指針。

而且由於指針Derived是不一樣的事,作爲一個指針Base,指針的指針Derived也是不一樣的東西作爲指針的指針Base

+0

它們共享公用內存大小。我可以肯定,我的Base **數組只包含Derived *對象,在很多情況下,您可以將Base *轉換爲Derived *,尤其是當您確定類型匹配時。 –

+1

標準拋開,如果不安全有沒有使用虛擬/多重繼承?無論如何,在現代流行的架構上,無論如何。 – krzaq

+0

@krzaq這就是我所說的,我可以堅持一些約束條件,如果它允許我加快代碼的速度。這裏的關鍵特性: –