У меня есть сценарий десериализации для иерархии объектов, в котором большинство объектов содержат указатели на другие объекты, но не владеют ими.
Я пытаюсь реализовать двухэтапный процесс, в котором:
Register(Object* pObject)
Идентифицируется в ID, данные читаются. Члены-указатели сериализуются как уникальные идентификаторы, поэтому, прочитав их, я RegisterResolver(int id, Object** ppMember)
s.*ppMember
(обратите внимание на разыменование).Эта проблема:
Base
класс должен быть зарегистрирован, однако Derived**
не может быть преобразован в Base**
,void*
(не void**
) тот Derived**
/ Base**
может быть преобразован в, но тогда так может Derived*
/ Base*
,В следующем сценарии:
struct A: public Serialized
{
int blah;
};
struct B: public Serialized
{
float fBlah;
A* pTarget;
};
B myB;
Если интерфейс RegisterResolver(int id, void* ppObject)
нет гарантии, что код клиента не пройдет myB.pTarget
вместо &myB.pTarget
,
Что я могу сделать, чтобы улучшить [type-] безопасность и удобочитаемость этого решения?
(Целевые платформы — x86 и ARM.)
Шаблон должен помочь. Как насчет
template<typename T>
void RegisterResolver(int id, T** ppObject, Base* extra = (T*)0);
Это позволяет аргумент любого типа Derived**
для которого есть неявное преобразование из Derived*
в Base*
,
Поскольку исходная проблема также касалась читабельности, и я хотел минимизировать потенциально запутанные параметры интерфейса, я повторил Бен Фойгтответ и закончился этим:
template<typename T>
void RegisterResolver(int id, T** ppObject)
{
// assert(ppObject != 0);
Base* pBase(*ppObject); // not used
// implementation
}