2015-01-02 143 views
0

我想指針存儲在一個數據結構中的不同類的對象(如陣列,HashMap的...)。據this answer我出來使用無類型指針void*和運營商&*(ClassName*)爲指針類型重鑄以下解決方案:存儲指針

#include <stdio.h> 
class ClassA{ public: int a; }; 
class ClassB{ public: double b; }; 
class Storage{ 
    public: 
    int n; 
    void** store; 
    Storage(int n_){ n = n_; store = new void*[n]; }; 
}; 
Storage s(5); 
int main(){ 
    // test store and load ClassA 
    ClassA a1; a1.a = 16;   
    s.store[ 0 ] = &a1; 
    ClassA* a2 = &*(ClassA*) s.store[ 0 ]; 
    printf( " a2 %i \n", a2->a); 
    // test store and load ClassB 
    ClassB b1; b1.b = 15.1455; 
    s.store[ 1 ] = &b1; 
    ClassB* b2 = &*(ClassB*) s.store[ 1 ]; 
    printf( " b2 %f \n", b2->b); 
} 

現在問題

  • 是什麼不好類似&*(ClassB*)的類型轉換除外,它不是類型安全的?
  • 是否有此類型轉換任何性能損失?
  • 有沒有更好的(更好,更安全,更快)的方式如何存儲指針,以在單個陣列中不同類的不同的對象?

  • 啊,我想通了,它實際上不是有用,使其void**因爲比我現在有辦法以後怎麼識別存儲對象的類型。最好是用模板和普通超類來做。像這樣

    #include <stdio.h> 
    #include <cstdlib> 
    template< class TYPE1 > class Storage{ 
        public: 
        int n; 
        TYPE1** store; 
        Storage(int n_){ n = n_; store = new TYPE1*[n];  }; // Constructor 
        void put(int key, TYPE1* obj){ store[key] = obj; }; // save data 
        TYPE1* get(int key   ){ return store[key]; }; // load data 
    }; 
    class Parent { public: int kind;                  }; 
    class ChildA : public Parent { public: int someData; ChildA(int someData_ ){ kind=0; someData =someData_; } }; 
    class ChildB : public Parent { public: double otherData; ChildB(double otherData_){ kind=1; otherData=otherData_; } }; 
    Storage<Parent> mixed(10); 
    int main(){ 
        srand(15454); 
        printf(" ==== initialize by random data and radom type \n"); 
        for(int i=0; i<mixed.n; i++){ 
         if ((rand()&4) > 0){ 
          int someData = rand()&0xFF; 
          mixed.put(i, new ChildA( someData)); 
          printf(" i %i ChildA.someData = %i \n", i , someData);  
         }else{ 
          double otherData = (rand()&0xFF)/256.0f; 
          mixed.put(i, new ChildB( otherData)); 
          printf(" i %i ChildB.otherData = %f \n", i , otherData); 
         }; 
        }; 
        printf(" ==== recall stored data \n"); 
        for(int i=0; i<mixed.n; i++){ 
         Parent* obj = mixed.get(i); 
         if (obj->kind ==0){ printf(" i %i ChildA.someData = %i \n", i , ((ChildA *) obj)->someData ); } 
         else     { printf(" i %i ChildB.otherData = %f \n", i , ((ChildB *) obj)->otherData); }; 
        }; 
    } 
    
    +2

    早在您感興趣的問題的標題:「我想要做壞事」的領土。然後用**來說,「是的,真的很糟糕,沒有什麼能阻止我,你聽到了!」。好的,尋求幫助的不協調。 –

    +0

    有更好的東西,例如['的std :: tuple'](http://en.cppreference.com/w/cpp/utility/tuple)。 –

    +0

    乾杯和hth。 - Alf> probaly它只是缺乏我的知識。你可以說得更詳細點嗎。還有什麼我可以做動態可分配的指針數組比**? –

    回答

    2

    是什麼不好類型轉換一樣&*(ClassB*)但它不是類型安全的?

    應用*隨後&一個指針是一個空操作,所以只需(ClassB*)應該足夠了。此外,您應該使用C++風格演員,在這種情況下,您可以使用static_cast<ClassB*>而不是C風格演員陣容,以使您的意思更加明確。

    壞的事情是,這不僅是不是類型安全的,但它也很混亂和C++語言的濫用。

    是否有此類型轉換任何性能損失?

    有沒有更好的(更好,更安全,更快)的方式如何存儲指針,以在單個陣列中不同類的不同的對象?

    是的,最好的辦法是分析出這些類型的共同行爲變成一個基類(可能是抽象的),並宣佈你的數組的指針存儲基類。如果沒有共同的行爲,那麼將它們全部存儲在同一個陣列中幾乎總是做錯的事情。如果由於某種原因你真的想要這樣做,像Boost.Any這樣的東西可能是正確的解決方案。

    +0

    第三個問題的答案很棒。 –

    +0

    謝謝。廣告3)如果我製作指向普通父類的指針數組,我仍然需要某種類型的向下(或不是?)。對我來說,似乎是一樣的。如果我認爲void *是ClassA和ClassB的共同父項,就像在Java中一樣,它是所有類的Object共同父項。 –

    +0

    @ProkopHapala是否需要下拉取決於是否打算稍後複製容器中的對象* out *。如果是這樣,請重新考慮您的設計。如果沒有,寫入虛擬函數並調用它們。如果你有虛函數,你也可以使用'dynamic_cast',這是類型安全的,不像'void *'中的'static_cast'。 – Brian