调用未知的构造函数(反射替换)c ++
Call a unknown constructor (Replacement for reflection) c++
我正在将我在 java/as3 中制作的网络 api 移植到 C++。我对 c++ 很陌生,所以我对所有可用的工具都不熟悉。
我有一个名为 Packet 的 class。在我的 java/as3 class 中,该数据包有 2 个哈希映射,一个用于 classToId,一个用于 idToClass。
然后我用一个 id 和它的 class 对象注册一个派生数据包。
收到数据包后,我会获取其数据包 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 class。(所以这个 class 将在使用这个 API 的应用程序中扩展)
典型的解决方案是使用工厂函数,将 ID 连接到实际 class。假设我们有一组 classes 来处理形状:
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;
}
另一种方法,如果您真的不知道 class 您想要什么,"until later" 是提供一个创建正确 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
是一个共同的基础-class。如果那不是真的,我不确定以 understand/explain 等
容易的方式解决这个问题有多容易
我正在将我在 java/as3 中制作的网络 api 移植到 C++。我对 c++ 很陌生,所以我对所有可用的工具都不熟悉。
我有一个名为 Packet 的 class。在我的 java/as3 class 中,该数据包有 2 个哈希映射,一个用于 classToId,一个用于 idToClass。
然后我用一个 id 和它的 class 对象注册一个派生数据包。
收到数据包后,我会获取其数据包 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 class。(所以这个 class 将在使用这个 API 的应用程序中扩展)
典型的解决方案是使用工厂函数,将 ID 连接到实际 class。假设我们有一组 classes 来处理形状:
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;
}
另一种方法,如果您真的不知道 class 您想要什么,"until later" 是提供一个创建正确 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
是一个共同的基础-class。如果那不是真的,我不确定以 understand/explain 等