2015-01-02 140 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