Angelscript/docs/manual/doc_adv_class_hierarchy.html

214 lines
20 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.18"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>AngelScript: Class hierarchies</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="aslogo_small.png"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">AngelScript
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.18 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('doc_adv_class_hierarchy.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Class hierarchies </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>AngelScript cannot automatically determine relationships between registered classes, so in order to establish the hierarchies for use within the script language it is necessary to do a bit more registration beyond the normal <a class="el" href="doc_register_type.html">object registration</a>.</p>
<p>Hierarchies can currently only be registered for <a class="el" href="doc_reg_basicref.html">reference types</a>, not for <a class="el" href="doc_register_val_type.html">value types</a>.</p>
<h1><a class="anchor" id="doc_adv_class_hierarchy_1"></a>
Establishing the relationship</h1>
<p>In order to let AngelScript know that two types are related you need to register the reference cast operators <a class="el" href="doc_script_class_ops.html#doc_script_class_conv">opCast</a> and <a class="el" href="doc_script_class_ops.html#doc_script_class_conv">opImplCast</a>. The opCast should be used if you only want to allow the cast through an explicit call with the <code><a class="el" href="doc_expressions.html#conversion">cast&lt;class&gt;</a></code> operator. opImplCast should be used when you want to allow the compiler to implicitly perform the cast as necessary.</p>
<p>Usually you'll want to use opImplCast for casts from a derived type to the base type, and opCast for casts from a base type to a derived type.</p>
<div class="fragment"><div class="line"><span class="comment">// Example opCast behaviour</span></div>
<div class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> A, <span class="keyword">class</span> B&gt;</div>
<div class="line">B* refCast(A* a)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// If the handle already is a null handle, then just return the null handle</span></div>
<div class="line"> <span class="keywordflow">if</span>( !a ) <span class="keywordflow">return</span> 0;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Now try to dynamically cast the pointer to the wanted type</span></div>
<div class="line"> B* b = <span class="keyword">dynamic_cast&lt;</span>B*<span class="keyword">&gt;</span>(a);</div>
<div class="line"> <span class="keywordflow">if</span>( b != 0 )</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Since the cast was made, we need to increase the ref counter for the returned handle</span></div>
<div class="line"> b-&gt;addref();</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">return</span> b;</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Example registration of the behaviour</span></div>
<div class="line">r = engine-&gt;<a class="code" href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">RegisterObjectMethod</a>(<span class="stringliteral">&quot;base&quot;</span>, <span class="stringliteral">&quot;derived@ opCast()&quot;</span>, <a class="code" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>((refCast&lt;base,derived&gt;)), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4ac08652c72f1cc0dc81c37812fab0e253">asCALL_CDECL_OBJLAST</a>); assert( r &gt;= 0 );</div>
<div class="line">r = engine-&gt;<a class="code" href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">RegisterObjectMethod</a>(<span class="stringliteral">&quot;derived&quot;</span>, <span class="stringliteral">&quot;base@ opImplCast()&quot;</span>, <a class="code" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>((refCast&lt;derived,base&gt;)), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4ac08652c72f1cc0dc81c37812fab0e253">asCALL_CDECL_OBJLAST</a>); assert( r &gt;= 0 );</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Also register the const overloads so the cast works also when the handle is read only </span></div>
<div class="line">r = engine-&gt;<a class="code" href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">RegisterObjectMethod</a>(<span class="stringliteral">&quot;base&quot;</span>, <span class="stringliteral">&quot;const derived@ opCast() const&quot;</span>, <a class="code" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>((refCast&lt;base,derived&gt;)), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4ac08652c72f1cc0dc81c37812fab0e253">asCALL_CDECL_OBJLAST</a>); assert( r &gt;= 0 );</div>
<div class="line">r = engine-&gt;<a class="code" href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">RegisterObjectMethod</a>(<span class="stringliteral">&quot;derived&quot;</span>, <span class="stringliteral">&quot;const base@ opImplCast() const&quot;</span>, <a class="code" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>((refCast&lt;derived,base&gt;)), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4ac08652c72f1cc0dc81c37812fab0e253">asCALL_CDECL_OBJLAST</a>); assert( r &gt;= 0 );</div>
</div><!-- fragment --><p>Note that it may be necessary to add extra parenthesis to the <code>asFUNCTION</code> macro so that the preprocessor doesn't interpret the <code>,</code> in the template declaration as the argument separator in the macro.</p>
<h1><a class="anchor" id="doc_adv_class_hierarchy_2"></a>
Inherited methods and properties</h1>
<p>Just as relationships cannot be determined, there is also no way to automatically let AngelScript add inherited methods and properties to derived types. The reason for this is that method pointers and property offsets may differ between the base class and derived class, especially when multiple inheritance is used, and there is no way to automatically determine exactly what the difference is.</p>
<p>For this reason the application needs to register all the inherited methods and properties for the derived classes, which may lead to a bit of duplicate code. However, you may be able to avoid the duplication through a bit of clever thinking. Here is an example of registering the methods and properties for a base class and the derived class (registration of behaviours has been omitted for briefness):</p>
<div class="fragment"><div class="line"><span class="comment">// The base class</span></div>
<div class="line"><span class="keyword">class </span>base</div>
<div class="line">{</div>
<div class="line"><span class="keyword">public</span>:</div>
<div class="line"> <span class="keyword">virtual</span> <span class="keywordtype">void</span> aMethod();</div>
<div class="line"> </div>
<div class="line"> <span class="keywordtype">int</span> aProperty;</div>
<div class="line">};</div>
<div class="line"> </div>
<div class="line"><span class="comment">// The derived class</span></div>
<div class="line"><span class="keyword">class </span>derived : <span class="keyword">public</span> base</div>
<div class="line">{</div>
<div class="line"><span class="keyword">public</span>:</div>
<div class="line"> <span class="keyword">virtual</span> <span class="keywordtype">void</span> aNewMethod();</div>
<div class="line"> </div>
<div class="line"> <span class="keywordtype">int</span> aNewProperty;</div>
<div class="line">};</div>
<div class="line"> </div>
<div class="line"><span class="comment">// The code to register the classes</span></div>
<div class="line"><span class="comment">// This is implemented as a template function, to support multiple inheritance</span></div>
<div class="line"><span class="keyword">template</span> &lt;<span class="keyword">class</span> T&gt;</div>
<div class="line"><span class="keywordtype">void</span> RegisterBaseMembers(<a class="code" href="classas_i_script_engine.html">asIScriptEngine</a> *engine, <span class="keyword">const</span> <span class="keywordtype">char</span> *type)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">int</span> r;</div>
<div class="line"> </div>
<div class="line"> r = engine-&gt;<a class="code" href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">RegisterObjectMethod</a>(type, <span class="stringliteral">&quot;void aMethod()&quot;</span>, <a class="code" href="angelscript_8h.html#a7345e6b3afabec24efd0ff77886d49a6">asMETHOD</a>(T, aMethod), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4aea516c8742acc1edff6a43dc1bb09e96">asCALL_THISCALL</a>); assert( r &gt;= 0 );</div>
<div class="line"> </div>
<div class="line"> r = engine-&gt;<a class="code" href="classas_i_script_engine.html#a0aa35bf824180fe6aed685b40f0e8c34">RegisterObjectProperty</a>(type, <span class="stringliteral">&quot;int aProperty&quot;</span>, <a class="code" href="angelscript_8h.html#a717eccea17214bc1eb64bb9789c4915a">asOFFSET</a>(T, aProperty)); assert( r &gt;= 0 );</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keyword">template</span> &lt;<span class="keyword">class</span> T&gt;</div>
<div class="line"><span class="keywordtype">void</span> RegisterDerivedMembers(<a class="code" href="classas_i_script_engine.html">asIScriptEngine</a> *engine, <span class="keyword">const</span> <span class="keywordtype">char</span> *type)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">int</span> r;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Register the inherited members by calling </span></div>
<div class="line"> <span class="comment">// the registration of the base members</span></div>
<div class="line"> RegisterBaseMembers&lt;T&gt;(engine, type);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Now register the new members</span></div>
<div class="line"> r = engine-&gt;<a class="code" href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">RegisterObjectMethod</a>(type, <span class="stringliteral">&quot;void aNewMethod()&quot;</span>, <a class="code" href="angelscript_8h.html#a7345e6b3afabec24efd0ff77886d49a6">asMETHOD</a>(T, aNewMethod), <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4aea516c8742acc1edff6a43dc1bb09e96">asCALL_THISCALL</a>); assert( r &gt;= 0 );</div>
<div class="line"> </div>
<div class="line"> r = engine-&gt;<a class="code" href="classas_i_script_engine.html#a0aa35bf824180fe6aed685b40f0e8c34">RegisterObjectProperty</a>(type, <span class="stringliteral">&quot;int aProperty&quot;</span>, <a class="code" href="angelscript_8h.html#a717eccea17214bc1eb64bb9789c4915a">asOFFSET</a>(T, aProperty)); assert( r &gt;= 0 );</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> RegisterTypes(<a class="code" href="classas_i_script_engine.html">asIScriptEngine</a> *engine)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">int</span> r;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Register the base type</span></div>
<div class="line"> r = engine-&gt;<a class="code" href="classas_i_script_engine.html#a29c6c087c8c5b5cdb6271cfd161cc5a6">RegisterObjectType</a>(<span class="stringliteral">&quot;base&quot;</span>, 0, <a class="code" href="angelscript_8h.html#a855d86fa9ee15b9f75e553ee376b5c7aa9450e038342b36c745858d2e5ae4b861">asOBJ_REF</a>); assert( r &gt;= 0 );</div>
<div class="line"> RegisterBaseMembers&lt;base&gt;(engine, <span class="stringliteral">&quot;base&quot;</span>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Register the derived type</span></div>
<div class="line"> r = engine-&gt;<a class="code" href="classas_i_script_engine.html#a29c6c087c8c5b5cdb6271cfd161cc5a6">RegisterObjectType</a>(<span class="stringliteral">&quot;derived&quot;</span>, 0, <a class="code" href="angelscript_8h.html#a855d86fa9ee15b9f75e553ee376b5c7aa9450e038342b36c745858d2e5ae4b861">asOBJ_REF</a>); assert( r &gt;= 0 );</div>
<div class="line"> RegisterDerivedMembers&lt;derived&gt;(engine, <span class="stringliteral">&quot;derived&quot;</span>);</div>
<div class="line">}</div>
</div><!-- fragment --> </div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div class="ttc" id="aclassas_i_script_engine_html_ad74043be9cc30f105c62f482ca720574"><div class="ttname"><a href="classas_i_script_engine.html#ad74043be9cc30f105c62f482ca720574">asIScriptEngine::RegisterObjectMethod</a></div><div class="ttdeci">virtual int RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &amp;funcPointer, asDWORD callConv, void *auxiliary=0, int compositeOffset=0, bool isCompositeIndirect=false)=0</div><div class="ttdoc">Registers a method for the object type.</div></div>
<div class="ttc" id="aangelscript_8h_html_a3ec92ea3c4762e44c2df788ceccdd1e4ac08652c72f1cc0dc81c37812fab0e253"><div class="ttname"><a href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4ac08652c72f1cc0dc81c37812fab0e253">asCALL_CDECL_OBJLAST</a></div><div class="ttdeci">@ asCALL_CDECL_OBJLAST</div><div class="ttdoc">A cdecl function that takes the object pointer as the last parameter.</div><div class="ttdef"><b>Definition:</b> angelscript.h:234</div></div>
<div class="ttc" id="aclassas_i_script_engine_html_a29c6c087c8c5b5cdb6271cfd161cc5a6"><div class="ttname"><a href="classas_i_script_engine.html#a29c6c087c8c5b5cdb6271cfd161cc5a6">asIScriptEngine::RegisterObjectType</a></div><div class="ttdeci">virtual int RegisterObjectType(const char *obj, int byteSize, asDWORD flags)=0</div><div class="ttdoc">Registers a new object type.</div></div>
<div class="ttc" id="aangelscript_8h_html_a855d86fa9ee15b9f75e553ee376b5c7aa9450e038342b36c745858d2e5ae4b861"><div class="ttname"><a href="angelscript_8h.html#a855d86fa9ee15b9f75e553ee376b5c7aa9450e038342b36c745858d2e5ae4b861">asOBJ_REF</a></div><div class="ttdeci">@ asOBJ_REF</div><div class="ttdoc">A reference type.</div><div class="ttdef"><b>Definition:</b> angelscript.h:250</div></div>
<div class="ttc" id="aclassas_i_script_engine_html"><div class="ttname"><a href="classas_i_script_engine.html">asIScriptEngine</a></div><div class="ttdoc">The engine interface.</div><div class="ttdef"><b>Definition:</b> angelscript.h:1092</div></div>
<div class="ttc" id="aangelscript_8h_html_a78f8f2c7f1c88b12e74a5ac47b4184ae"><div class="ttname"><a href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a></div><div class="ttdeci">#define asFUNCTION(f)</div><div class="ttdoc">Returns an asSFuncPtr representing the function specified by the name.</div><div class="ttdef"><b>Definition:</b> angelscript.h:675</div></div>
<div class="ttc" id="aangelscript_8h_html_a7345e6b3afabec24efd0ff77886d49a6"><div class="ttname"><a href="angelscript_8h.html#a7345e6b3afabec24efd0ff77886d49a6">asMETHOD</a></div><div class="ttdeci">#define asMETHOD(c, m)</div><div class="ttdoc">Returns an asSFuncPtr representing the class method specified by class and method name.</div><div class="ttdef"><b>Definition:</b> angelscript.h:740</div></div>
<div class="ttc" id="aangelscript_8h_html_a3ec92ea3c4762e44c2df788ceccdd1e4aea516c8742acc1edff6a43dc1bb09e96"><div class="ttname"><a href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4aea516c8742acc1edff6a43dc1bb09e96">asCALL_THISCALL</a></div><div class="ttdeci">@ asCALL_THISCALL</div><div class="ttdoc">A thiscall class method.</div><div class="ttdef"><b>Definition:</b> angelscript.h:232</div></div>
<div class="ttc" id="aclassas_i_script_engine_html_a0aa35bf824180fe6aed685b40f0e8c34"><div class="ttname"><a href="classas_i_script_engine.html#a0aa35bf824180fe6aed685b40f0e8c34">asIScriptEngine::RegisterObjectProperty</a></div><div class="ttdeci">virtual int RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset=0, bool isCompositeIndirect=false)=0</div><div class="ttdoc">Registers a property for the object type.</div></div>
<div class="ttc" id="aangelscript_8h_html_a717eccea17214bc1eb64bb9789c4915a"><div class="ttname"><a href="angelscript_8h.html#a717eccea17214bc1eb64bb9789c4915a">asOFFSET</a></div><div class="ttdeci">#define asOFFSET(s, m)</div><div class="ttdoc">Returns the offset of an attribute in a struct.</div><div class="ttdef"><b>Definition:</b> angelscript.h:672</div></div>
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated on Sat Dec 5 2020 23:20:24 for AngelScript by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.18 </li>
</ul>
</div>
</body>
</html>