2015-02-07 79 views
0

我将我在java/as3中创建的网络api移植到C++。我对C++很陌生,所以我不熟悉所有可用的工具。调用一个未知的构造函数(替代反射)C++

我有一个叫Packet的类。在我的java/as3类中,数据包有2个hashmaps,一个用于classToId,另一个用于idToClass。

然后我注册一个带有id和它的类对象的派生包。

当收到一个包时,我得到它的包ID,然后用这个ID创建一个新的包。

在AS3代码然后我用:

public static function getNewPacket(id:int):Packet 
    { 
     try 
     { 
      var clazz:Class = getClassById[id]; 
      return (clazz == null ? null : Packet(new clazz())); 
     } 
     catch (e:Error) 
     { 
      trace("Skipping packet with id " + id + ": " + e.message); 
     } 
     return null; 
    } 

正如你所看到的,使用反射调用构造函数。然而,在c + +中,我不知道如何创建这个。 我不能使用静态数据包列表,因为这是一个API类(所以这个类会在使用这个API的应用程序中扩展)

+0

底线 - C++中没有'reflection'。你需要考虑“在Java框外”来提出一个解决方案。 – PaulMcKenzie 2015-02-07 23:58:27

+0

这就是为什么我问这个问题,我不知道可用来替代反射的工具。 – Duckdoom5 2015-02-08 00:00:48

+0

可以存储在'getClassById'映射中的'Class's有什么约束?他们可以是任何具有无参数构造函数的类,还是需要成为某个基类的子类 - 它是在您的应用中定义的基类还是其他类?还是有一个可接受的类的简短列表? – ajb 2015-02-08 00:01:38

回答

2

典型的解决方案是有一个工厂函数,它将ID到实际的班级。假设我们有一组类来处理形状:

class Shape { ... }; 
class Square : public Shape { ... } ; 
class Triangle : public Shape { ... }; 

enum ShapeID { SquareID, TriangleID, ... } 

Shape *shapeFactory(ShapeID id) 
{ 
    switch(id) 
    { 
     case SquareID: return new Square; 
     case TriangleID: return new Triangle; 
     ... 
    }; 
    return NULL; 
} 

的选择,如果你真的不知道自己想要什么课“直到后来”是提供创建正确ID的功能。

所以,如果你想成为能够与用户自定义形状,以延长你的形状的系统,你可以做这样的事情:

typedef Shape* (*shapeCreatorFunc)(); 
... 

Shape* createStar() 
{ 
    return new Star; 
} 

... 
typedef std::map<ID, ShapeCreatorFunc> ShapeMap; 
ShapeMap map; 
... 
map[SquareID] = createSquare; 
map[TriangleID] = createTriangle; 
map[StarID] = createStar; 
.... 
ShapeMap::iterator it = map.find(id); 
if (it != map.end()) 
{ 
    Shape *s = it.second(); 
} 

这仍然依赖于Shape是一个共同的基类。如果不是这样,我不确定用易于理解/解释的方式解决这个问题是多么容易。

+0

感谢队友,正是我在找的东西。底部解决方案为我解决了:) – Duckdoom5 2015-02-08 00:05:16