⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oopc.html

📁 c语言是面向过程的程序语言
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<br><tt><b>classMethodDecl_</b>(*const new) char const name[], char constdepartment[] <b>__</b></tt><br><tt>{</tt><br><tt>&nbsp; t_employee *const this = employee.alloc();</tt><br><tt>&nbsp; employee.init(this, name, department);</tt><br><tt>&nbsp; return this;</tt><br><tt>}</tt><p><tt>void</tt><br><tt><b>methodDecl_</b>(init) char const name[], char const department[]<b>__</b></tt><br><tt>{</tt><br><tt>&nbsp; /* super() upcast this from employee to person */</tt><br><tt>&nbsp; person.init(<b>super</b>(<b>this</b>,person), name);</tt><br><tt>&nbsp; <b>this</b>->m.department = strdup(department);</tt><br><tt>}</tt><p><tt>void</tt><br><tt><b>methodDecl_</b>(copy) t_employee const*const emp <b>__</b></tt><br><tt>{</tt><br><tt>&nbsp; employee._employee(<b>this</b>);</tt><br><tt>&nbsp; employee.init(<b>this</b>, emp->m.person.m.name, emp->m.department);</tt><br><tt>}</tt><p><b><tt>CLASS_IMPLEMENTATION</tt></b><p><tt>&nbsp; <b>methodName</b>(new),</tt><br><tt>&nbsp; <b>methodName</b>(init),</tt><br><tt>&nbsp; <b>methodName</b>(copy)</tt><p><b><tt>ENDOF_IMPLEMENTATION</tt></b></blockquote>The <tt>SUPERCLASS</tt> macro declares <tt>person</tt> as a superclassof <tt>employee</tt>. Like for the methods declarations, it must appearin the same order and place as in the beginning of the interface definition.The <tt>initClassDecl()</tt> which this time is not empty, is automaticallycalled <b><u>once</u></b> by the constructor to properly initialize thesuperclass <tt>person</tt> and therefore guarantee the validity of the<tt>employee</tt>class. The rest of the file looks like the person implementation adaptedfor employee, it means that employee<tt>init()</tt> and <tt>_employee()</tt>class methods call first the person <tt>init()</tt> and<tt>_person()</tt>class methods. Finally the overloaded <tt>print</tt> object method of person(same slot in <tt>vtbl</tt>) <i>calls</i> the person <tt>print</tt> methodanddisplay information related to employee only (i.e. the department). Sinceno new object method has been defined for employee, the size of the virtualtable of <tt>employee</tt> is the same as the size of the virtual tableof <tt>person</tt>.<p>The <tt>super</tt> macro (equivalent to <tt>super_cast()</tt>) usedin the methods implementation above <i>upcast </i><tt>this</tt> which isan employee (<tt>t_employee</tt>) to a person (<tt>t_person</tt>). Everytime you need to <i>send a message</i> or <i>call a method</i> of a <i>superclass</i>,you must use <tt>super(<i>object</i>, <i>superclass</i>)</tt> to upcastthe object into a <i>superobject</i>. Since a class may inherit from severalsuperclasses (see <a href="#Multiple_Inheritance">Multiple Inheritance</a>),the full member name (without the first <tt>m</tt>) of the superclass mustbe provided. To reach a <i>superobject</i> public members of an object,you do exactly as for normal class:<blockquote><tt><b>super</b>(<i>object</i>, <i>super</i>)->m.<i>public_member</i></tt>.</blockquote>The <tt>sub_cast()</tt> macro used in the methods implementation above<i>downcast</i><tt>this</tt>which is a person (<tt>t_person</tt>) to an employee (<tt>t_employee</tt>).Every time you need to reach the <i>subclass</i> in its implementation,you must use <tt>sub_cast(<i>object</i>, <i>superclass</i>)</tt> to downcastthe <i>superobject</i> into the implemented object. Since the subclassmay inherit from several superclasses (see <a href="#Multiple_Inheritance">MultipleInheritance</a>), the full member name (without the first <tt>m</tt>) ofthe superclass must be provided. To reach the <i>subobject</i> public membersof an object, you can do:<blockquote><tt><b>sub_cast</b>(<i>object</i>, <i>super</i>)->m.<i>public_member</i></tt>.</blockquote>In fact, <tt>sub_cast()</tt> is only available in implementation and refersto the definition of <tt>OBJECT</tt> to know the subclass name.<p>To summarize, <tt>super_cast()</tt> (or <tt>super()</tt>) upcast a subclassto a superclass while <tt>sub_cast()</tt> downcast a superclass to the<tt>OBJECT</tt>subclass. Both are static cast resolved a compilation time.<br>&nbsp;<table CELLPADDING=5 COLS=1 WIDTH="100%" BGCOLOR="#66FFFF" NOSAVE ><tr NOSAVE><td NOSAVE><a NAME="Multiple_Inheritance"></a><b><font face="Arial,Helvetica"><font size=+2>MultipleInheritance</font></font></b></td></tr></table><p>Multiple inheritance can be easily achieved in the same way as singleinheritance (see <a href="#Inheritance">Inheritance</a>) by duplicatingapproprialty <tt>INHERIT_MEMBERS_OF()</tt>, <tt>INHERIT_METHODS_OF()</tt>,<tt>SUPERCLASS()</tt>and <tt>initSuper()</tt> definition and declarations. Assuming the existenceof the superclasses<tt>class1</tt>,<tt>class2</tt> and of the class <tt>aClass</tt>which inherits from both superclasses. Starting from single inheritance,some modifications have to be done in interface:<blockquote><tt>#ifndef ACLASS_H</tt><br><tt>#define ACLASS_H</tt><p><tt>#include &lt;class1.h></tt><br><tt>#include &lt;class2.h></tt><p><tt>#undef&nbsp; OBJECT</tt><br><tt>#define <b>OBJECT</b> aClass</tt><p><b><tt>OBJECT_INTERFACE</tt></b><p><tt>&nbsp; <b>INHERIT_MEMBERS_OF</b> (class1);</tt><br><tt>&nbsp; <b>INHERIT_MEMBERS_OF</b> (class2);</tt><br><tt>&nbsp; ...</tt><br><b><tt>OBJECT_METHODS</tt></b><p><tt>&nbsp; <b>INHERIT_METHODS_OF</b> (class1);</tt><br><tt>&nbsp; <b>INHERIT_METHODS_OF</b> (class2);</tt><br><tt>&nbsp; ...</tt><br><b><tt>ENDOF_INTERFACE</tt></b><br>&nbsp;<p><b><tt>CLASS_INTERFACE</tt></b><br><tt>&nbsp; ...</tt><br><b><tt>ENDOF_INTERFACE</tt></b><p><tt>#endif</tt></blockquote>as well as in implementation:<blockquote><tt>...</tt><br><b><tt>OBJECT_IMPLEMENTATION</tt></b><p><tt>&nbsp; <b>SUPERCLASS</b> (class1),</tt><br><tt>&nbsp; <b>SUPERCLASS</b> (class2),</tt><br><tt>&nbsp; ...</tt><br><b><tt>ENDOF_IMPLEMENTATION</tt></b><p><tt><b>initClassDecl</b>()</tt><br><tt>{</tt><br><tt>&nbsp; ...</tt><br><tt>&nbsp; <b>initSuper</b>(class1);</tt><br><tt>&nbsp; <b>initSuper</b>(class2);</tt><br><tt>&nbsp; ...</tt><br><tt>}</tt><br><tt>...</tt><br><b><tt>CLASS_IMPLEMENTATION</tt></b><br><tt>&nbsp; ...</tt><br><b><tt>ENDOF_IMPLEMENTATION</tt></b></blockquote>And that is all. As previously mentioned, superclasses declaration mustbe done at the beginning of each section of the object interface and mustbe at the same place in the object implementation. Sending a message toa superclass is identical to single inheritance:<blockquote><tt><b>sendMsg</b>(<b>super</b>(<i>object</i>, <i>superclass</i>),<i>message</i>);</tt></blockquote>If you inherit twice (two levels of inheritance), you should do:<blockquote><tt><b>sendMsg</b>(<b>super</b>(<i>object</i>, <i>superclass.m.supersuperclass</i>),<i>message</i>);</tt></blockquote>and so on. The advantage of specifying the superclass name is that youcan choose which superclass receives the message (two superclasses mayanswer to the same message).<p>But it can become quickly boring to use <tt>super()</tt> each time youhave to send a message to your superclasses, or you may want to send thesame message to all your superclasses at the same time. In that case, thebest thing to do is to declare in your <tt>aClass</tt> a method using thesame name (i.e. <tt>the_message</tt>) with a declaration which should looklike:<blockquote><tt>void</tt><br><tt><b>methodDecl</b>(the_message)</tt><br><tt>{</tt><br><tt>&nbsp; <b>sendCMsg</b>(<b>super</b>(this,class1),class1,the_message);</tt><br><tt>&nbsp; <b>sendCMsg</b>(<b>super</b>(this,class2),class2,the_message);</tt><br><tt>}</tt></blockquote>Now, assuming <i><tt>object</tt></i> to be of class <tt>aClass</tt>,<tt>sendMsg(<i>object</i>,the_message);</tt> in a program will send automatically the correct messageto all your<br>superclasses. This way of doing respects the polymorphism (if any,see <a href="#Polymorphism">Polymorphism</a>) of your class and of itssuperclasses.<br>&nbsp;<table CELLPADDING=5 COLS=1 WIDTH="100%" BGCOLOR="#66FFFF" NOSAVE ><tr NOSAVE><td NOSAVE><a NAME="Polymorphism"></a><b><font face="Arial,Helvetica"><font size=+2>Polymorphism</font></font></b></td></tr></table><p>The polymorphism is the aptitude of an object to be used as anotherobject while keeping its original behavior. This section assume the followinginheritance hierarchy:<blockquote><tt>manager --> employee --> person</tt><br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --> education</tt></blockquote>where <tt>--></tt> indicates the class derivation. For a complete interfaceand implementation of these objects see <tt><a href="examples/person.h">person.h</a></tt>,<tt><a href="examples/person.c">person.c</a></tt>,<tt><a href="examples/employee.h">employee.h</a></tt>,<tt><a href="examples/employee.c">employee.c</a></tt>,<tt><a href="examples/education.h">education.h</a></tt>,<tt><a href="examples/education.c">education.c</a></tt>,<tt><a href="examples/manager.h">manager.h</a></tt>and<tt><a href="examples/manager.c">manager.c</a></tt>.<p>One important thing in these classes is the overload of their <tt>print</tt>method, like for the manager example:<blockquote><tt>void</tt><br><tt><b>constMethodOvldDecl</b>(print, person)</tt><br><tt>{</tt><br><tt>&nbsp; /* this is a person */</tt><br><tt>&nbsp; /* send the print person message to this as an employee*/</tt><br><tt>&nbsp; <b>sendCMsg</b>(this, employee, person.print);</tt><br><tt>&nbsp; /* send the print person message to this as an education*/</tt><br><tt>&nbsp; <b>sendCMsg</b>(<b>super</b>(<b>sub_cast</b>(this,employee.m.person),education),education,print);</tt><br><tt>&nbsp; printf("\tlevel:\t%d\n", <b>sub_cast</b>(this,employee.m.person)->m.level);</tt><br><tt>}</tt><p><tt>...</tt><p><tt><b>initClassDecl</b>()</tt><br><tt>{</tt><br><tt>&nbsp; <b>initSuper</b>(employee);</tt><br><tt>&nbsp; <b>initSuper</b>(education);</tt><br><tt><b>&nbsp; overload</b>(employee.person.print) = <b>methodOvldName</b>(print,person);</tt><br><tt>&nbsp; ...</tt><br><tt>}</tt></blockquote>This overloading mechanism change the manager virtual table slot <tt>employe.person.print</tt>which initially points to the person <tt>print</tt> message, to pointingto the <tt>print</tt> message defined above. This new message call the<tt>print</tt>message of the <tt>employee</tt> and <tt>education</tt> classes using <tt>sendCMsg()</tt>to avoid infinite loop and then print information related to <tt>manager</tt>.Inside implementation, as you can see, you can change from one superclassto another by using a combination of <tt>sub_cast()</tt> and <tt>super_cast()</tt>.Outside implementation you have to either use <tt>static_cast(this, employee.m.person,manager)</tt> (unsafe) and use <tt>super_cast()</tt> to get the superclassor to use <tt>dynamic_cast(this, education)</tt>. The latter is slowerbut safe since it behaves exactly as the C++ <tt>dynamic_cast</tt> operator.<p>The following example shows how to display all information of a personwhatever it is a person, an employee or a manager (see <tt><a href="examples/test_manager.c">test_manager.c</a></tt>for a complete example). The small program:<blockquote><tt>#include &lt;manager.h></tt><p><tt>void print_person(t_person *const per)</tt><br><tt>{</tt><br><tt>&nbsp; <b>sendMsg</b>(per, print);</tt><br><tt>}</tt><p><tt>int main(void)</tt><br><tt>{</tt><br><tt>&nbsp; t_person&nbsp;&nbsp; *const per = person&nbsp; .new("Brown");</tt><br><tt>&nbsp; t_employee *const emp = employee.new("Smith", "Cars");</tt><br><tt>&nbsp; t_manager&nbsp; *const mng = manager .new("Collins", "Trucks","PhD", 2);</tt><p><tt>&nbsp; print_person(per);</tt><br><tt>&nbsp; print_person(<b>super</b>(emp,person));</tt><br><tt>&nbsp; print_person(<b>super</b>(mng,employee.m.person));</tt><p><tt>&nbsp; <b>delete</b>(per);</tt><br><tt>&nbsp; <b>delete</b>(emp);</tt><br><tt>&nbsp; <b>delete</b>(mng);</tt><p><tt>&nbsp; return EXIT_SUCCESS;</tt><br><tt>}</tt></blockquote>will gives the output:<blockquote><tt>name: Brown</tt><br><tt>name: Smith</tt><br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dept: Cars</tt><br><tt>name: Collins</tt><br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dept: Trucks</tt><br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dipl: PhD</tt><br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; level: 2</tt></blockquote>and we see that the function <tt>print_employee() </tt>does not need distinguisha person from an employee or a manager. The polymorphism is achieved bythe message <tt>print</tt> in the function <tt>print_person</tt>. Using<tt>sendMsg()</tt>always ensures to refer to the right virtual table (through<tt>__vptr</tt>)and therefore to call the appropriate object method.<p>To simplify polymorphism implementation, <tt>ooc.h</tt> also providesfew interesting macros:<ul><li><tt>className(<i>object</i>)</tt> returns a constant string which c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -