На данный момент иерархии могут быть зарегистрированны только для ссылочных типов, не для типов-значений.
приведения.
asBEHAVE_IMPLICIT_REF_CAST стоит использовать если вы хотите, чтобы компилятор выполнял приведения типов неявно по мере необходимости.
Обычно используется asBEHAVE_IMPLICIT_REF_CAST для приведения типа от наследованного к базовому, а asBEHAVE_REF_CAST - от базового к наследуемому.
// Пример REF_CAST template<class A, strong> B* refCast(A* a) { // Если хенлд нулевой, то просто вернем его if( !a ) return 0; // Пытаемся динамически привести указатель к желаемому типу B* b = dynamic_cast<B*>(a); if( b != 0 ) { // После приведения увеличим счетчик ссылок для возвращаемого хендла b->addref(); } return b; } // Пример регистрации r = engine->RegisterObjectBehaviour("base", asBEHAVE_REF_CAST, "derived@ f()", asFUNCTION((refCast)), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("derived", asBEHAVE_IMPLICIT_REF_CAST, "base@ f()", asFUNCTION((refCast )), asCALL_CDECL_OBJLAST); assert( r >= 0 );
Заметим, что может быть необходимо добавить дополнительные скобки к макросу asFUNCTION чтобы препроцессор не интерпретировал , в шаблоне как разделитель аргументов.
Помните, что скрипт спокойно реагирует на нулевые указатели, в этом случае результат также будет нулевой. Это значит что приведение типов не должно быть представлено виртуальным методом класса, потому что вызов приведет к ошибке в случае нулевого указателя.
// Базовый класс class base { public: virtual void aMethod(); int aProperty; }; // Наследуемый класс class derived : public base { public: virtual void aNewMethod(); int aNewProperty; }; // Регистрация представлена шаблоном, с поддержкой множественного наследования template <class T> void RegisterBaseMembers(asIScriptEngine *engine, const char *type) { int r; r = engine->RegisterObjectMethod(type, "void aMethod()", asMETHOD(T, aMethod), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectProperty(type, "int aProperty", offsetof(T, aProperty)); assert( r >= 0 ); } template <class T> void RegisterDerivedMembers(asIScriptEngine *engine, const char *type) { int r; // Наследуемые классы регистрируем вызовом регистрации базового класса RegisterBaseMembers(engine, type); // Регистрируем новые члены r = engine->RegisterObjectMethod(type, "void aNewMethod()", asMETHOD(T, aNewMethod), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectProperty(type, "int aProperty", offsetof(T, aProperty)); assert( r >= 0 ); } void RegisterTypes(asIScriptEngine *engine) { int r; // Регистрируем базовый тип r = engine->RegisterObjectType("base", 0, asOBJ_REF); assert( r >= 0 ); RegisterBaseMembers (engine, "base"); // Регистрируем наследуемый тип r = engine->RegisterObjectType("derived", 0, asOBJ_REF); assert( r >= 0 ); RegisterDerivedMembers (engine, "derived"); }