将不同类型的指针存储在一个数组中

时间:2015-01-02 22:59:25

标签: c++ pointers type-conversion

我想在一个数据结构中存储指向不同类对象的指针(例如数组,HashMap ......)。根据{{​​3}},我使用无类型指针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 );
}

现在问题

  1. 类似于&*( ClassB* )的类型转换有什么不好,除非它不是类型安全的吗?
  2. 此类型转换是否有任何性能成本?
  3. 有没有更好的(更好,更安全,更快)的方式如何在单个数组中存储指向不同类的不同对象的指针?

  4. 啊,我发现它实际上没有用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 ); };
        };
    }
    

1 个答案:

答案 0 :(得分:3)

  

类似&*( ClassB* )的类型转换有什么不好,除非它不是类型安全的吗?

*后跟&应用于指针是无操作,因此只需(ClassB*)就足够了。此外,你应该使用C ++风格的强制转换,在这种情况下static_cast<ClassB*>,而不是C风格的强制转换,以使你的意思更明确。

不好的是,这不仅不是类型安全的,而且还非常混乱和滥用C ++语言。

  

此类型转换是否有任何性能成本?

没有

  

有没有更好的(更好,更安全,更快)的方式如何在单个数组中存储指向不同类的不同对象的指针?

是的,最好的方法是将这些类型的常见行为分解为基类(可能是抽象的),并声明您的数组存储指向该基类的指针。如果没有共同的行为,那么将它们全部存储在同一个数组中几乎总是错误的。如果由于某种原因你真的想这样做,Boost.Any之类的东西可能是正确的解决方案。