【问题标题】:Store pointers of different type in one array将不同类型的指针存储在一个数组中
【发布时间】:2015-01-02 22:59:24
【问题描述】:

我想将指向不同类对象的指针存储在一个数据结构中(例如数组、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 );
}

现在问题

  1. 除了类型不安全之外,像&amp;*( ClassB* ) 这样的类型转换有什么不好的吗?
  2. 这种类型转换是否有任何性能成本?
  3. 有没有更好(更好、更安全、更快)的方法如何将指向不同类的不同对象的指针存储在单个数组中?

啊,我发现将其设为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 ); };
    };
}

【问题讨论】:

  • 已经在你进入“我想做坏事”领域的问题标题中。然后用** 你说,“是的,真的很糟糕,没有什么能阻止我,你听到了吗!?”。寻求帮助的矛盾,嗯。
  • 有更好的东西,例如std::tuple.
  • 干杯和hth。 - Alf > 可能只是缺乏我的知识。你可以说得更详细点吗。除了 ** 之外,我还能如何动态分配指针数组?

标签: c++ pointers type-conversion


【解决方案1】:

除了类型不安全之外,像&amp;*( ClassB* ) 这样的类型转换有什么不好的吗?

* 后跟&amp; 应用于指针是无操作的,因此只需(ClassB*) 就足够了。此外,您应该使用 C++ 风格的转换,在本例中为 static_cast&lt;ClassB*&gt;,而不是 C 风格的转换,以使您的意思更明确。

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

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

没有。

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

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

【讨论】:

  • 第三个问题的答案太棒了。
  • 谢谢。广告 3)如果我创建指向公共父类的指针数组,我仍然需要一些类型向下转换(或不需要?)。对我来说似乎是一样的。如果我认为 void* 是 ClassA 和 ClassB 的共同父级,就像 Java 中的 Object 是所有类的共同父级一样。
  • @ProkopHapala 是否需要向下转换取决于您是否打算稍后将对象 out 复制到容器中。如果是这样,请重新考虑您的设计。如果没有,请编写虚函数并调用它们。如果你有虚函数,你也可以使用dynamic_cast,它是类型安全的,不像static_cast来自void*
  • @Brian: [详细] &amp;*pointer 可能与 pointer 不同,operator &amp; 重载。
  • @Jarod42 好点。我一直忘记那里有扭曲的人会超载地址运算符:-P
猜你喜欢
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多