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

📄 oopc.html

📁 c语言是面向过程的程序语言
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<tt>print</tt>does not change the object state, it is declared as a <i>constant objectmethod</i>.<p>Once the <tt>person</tt> interface is properly defined and includedinto your file, the following things are available:<ul><li>The <i>type</i> <tt>t_person</tt>. This is the <i>object type</i>.</li><li>The <i>class</i> <tt>person</tt>. This is the <i>object class</i> itself(instance).</li><li>The <i>class method</i> <tt>person()</tt>. This is the object <i>constructor</i>.A typical use is <tt>t_person per = person.person();</tt></li><li>The <i>class method</i> <tt>alloc()</tt>. This is the object <i>allocator</i>.A typical use is <tt>t_person *const per = person.alloc(); </tt>May throw<tt>ooc_bad_alloc</tt>exception.</li><li>The <i>generic type</i> <tt>t_OBJECT</tt>. It is equivalent to <tt>t_person</tt>except for genericity. Typically used in generic object interface and implementation.</li></ul>In addition, the object designer must provide the already declared butnot defined destructor:<ul><li>The <i>method</i> <tt>_person()</tt>. This is the object <i>destructor</i>.A typical use is <tt>person._person(per);</tt></li></ul>Finally, it is very common to find the <tt>init</tt> (or variants) method:<ul><li>The <i>method</i> <tt>init()</tt>. This method does non-constant objectinitialization, including dynamic initializations like arrays allocationor string duplication. A typical use is <tt>person.init(per, "Brown");</tt></li></ul>Finally, it is common to find (but not always, see <a href="#Abstract_Class">AbstractClass</a>) the<i>object factory</i> <tt>new</tt> (or variants) which mostof the time simply calls the allocator <tt>alloc()</tt> and the initializator<tt>init()</tt>with the new allocated object. That is why <tt>new()</tt> usually waitsfor the same arguments as <tt>init()</tt>.<p><b><u>Warning</u></b>: Do not confound the <tt>new()</tt> class method,the allocator and the constructor! The constructor <tt><i>object</i>()</tt>returns a well formed default object copy with all fields set to zero plusstatic initialization specified in <tt>initClassDecl()</tt> (see <a href="#Implementation">Implementation</a>),the allocator <tt>alloc()</tt> allocates an object and <i>calls the constructor</i>and <tt>new()</tt> <i>calls the allocator</i> and <tt>init()</tt>.<br>&nbsp;<table CELLPADDING=5 COLS=1 WIDTH="100%" BGCOLOR="#66FFFF" NOSAVE ><tr NOSAVE><td NOSAVE><a NAME="Implementation"></a><b><font face="Arial,Helvetica"><font size=+2>Implementation</font></font></b></td></tr></table><p>The implementation is the hidden side of the class. Only class designersare concerned by the class implementation which take place into a separateC file (<tt><a href="examples/person.c">person.c</a></tt>) with the samename as the class interface header file (<tt><a href="examples/person.h">person.h</a></tt>).A good advise would be to always design entirely the interface first andthen to program the implementation. This should help you to concentrateon object data and methods which is the most important part of your classand to postpone technical problems at development time. It is time nowto have a look to the implementation:<blockquote><tt>#include &lt;stdio.h></tt><p><tt>#define <b>IMPLEMENTATION</b></tt><p><tt>#include &lt;person.h></tt><p><tt>void</tt><br><tt><b>constMethodDecl</b>(print)</tt><br><tt>{</tt><br><tt>&nbsp; printf("name:\t%s\n", <b>this</b>->m.name);</tt><br><tt>}</tt><p><b><tt>BASEOBJECT_IMPLEMENTATION</tt></b><p><tt>&nbsp; <b>methodName</b>(print)</tt><p><b><tt>ENDOF_IMPLEMENTATION</tt></b><p><tt><b>initClassDecl</b>() {} /* class ctor, required */</tt><p><tt><b>dtorDecl</b>() /* object dtor, required */</tt><br><tt>{</tt><br><tt>&nbsp; free((void*)<b>this</b>->m.name);</tt><br><tt>&nbsp; <b>this</b>->m.name = NULL;</tt><br><tt>}</tt><p><tt>t_person</tt><br><tt><b>classMethodDecl_</b>(*const new) char const name[] <b>__</b></tt><br><tt>{</tt><br><tt>&nbsp; t_person *const this = person.alloc();</tt><br><tt>&nbsp; person.init(this, name);</tt><br><tt>&nbsp; return this;</tt><br><tt>}</tt><p><tt>void</tt><br><tt><b>methodDecl_</b>(init) char const name[] <b>__</b></tt><br><tt>{</tt><br><tt>&nbsp; <b>this</b>->m.name = strdup(name);</tt><br><tt>}</tt><p><tt>void</tt><br><tt><b>methodDecl_</b>(copy) t_person const*const per <b>__</b></tt><br><tt>{</tt><br><tt>&nbsp; person._person(<b>this</b>);</tt><br><tt>&nbsp; person.init(<b>this</b>, per->m.name);</tt><br><tt>}</tt><p><b><tt>CLASS_IMPLEMENTATION</tt></b><p><tt>&nbsp; methodName(new),</tt><br><tt>&nbsp; methodName(init),</tt><br><tt>&nbsp; methodName(copy)</tt><p><b><tt>ENDOF_IMPLEMENTATION</tt></b><br>&nbsp;</blockquote>The file starts by the definition of the keyword <tt>IMPLEMENTATION</tt>followed by the inclusion of the person interface. It is important to include<tt>person.h</tt><b><u>after</u></b>the <tt>IMPLEMENTATION</tt> definition otherwise its content would be differentand you would not be able to reach the object private member <tt>name</tt>or to use most of the keywords displayed in bold in the listing above.<p>Then follows the object methods definitions. The use of the keyword<tt>methodDecl</tt>,<tt>constMethodDecl</tt>and <tt>classMethodDecl</tt> helps to declare correctly the methods, theconstant object methods and the class methods. All methods have the storageclass specifier <tt>static</tt> which guarantees the encapsulation of themethods into the implementation module (i.e. the file). Since the<tt>static</tt>storage specifier is included into the<tt>methodDecl</tt>, <tt>constMethodDecl</tt>and <tt>classMethodDecl</tt> macros, pointers qualifier <tt>*</tt> and<tt>const</tt>have to be put with the method name, not with the returned type (i.e. <tt>charmethodDecl(*const getName);</tt>). A clean solution to avoid this littleannoyance is to define the returned pointer type with<tt>typedef</tt>locally to the implementation. Macros<tt>methodDecl</tt>,<tt>constMethodDecl</tt>and <tt>classMethodDecl</tt>have their equivalent version with variablenumber of arguments: <tt>methodDecl_</tt>,<tt>constMethodDecl_</tt> and<tt>classMethodDecl_</tt>.<p>Then follows the object implementation delimited by <tt>(BASE)OBJECT_IMPLEMENTATION</tt>and<tt>ENDOF_IMPLEMENTATION</tt> and inside these tags you find the listof the object methods <b>in the same order as declared in the object methodsinterface</b>. Whatever, the compiler will complain if the order is notrespected (except if two successive methods have the same prototype!).<p>Then follows the <i>required</i> <tt>initClassDecl()</tt> declarationwhich is a special local function where class initializations are donelike default object initialization (returned by the constructor), superclassesinitialization (see <a href="#Inheritance">Inheritance</a>) or functionsoverloading (see <a href="#Polymorphism">Polymorphism</a>). <i>Defaultstatic object</i> initializations can be achieved by assigning defaultvalues (by default all fields are set to zero) to members using <tt>objDefault()</tt>(i.e. <tt>objDefault(level) = 1;</tt> in <tt><a href="examples/manager.c">manager.c</a></tt>).The destructor <tt>_person()</tt> declared by <tt>dtorDecl()</tt> is always<i>required</i>even if it is empty like <tt>initClassDecl()</tt> is this example.<p>Then follows the methods and class methods definitions. Again the methoddeclarations are done with the<tt>methodDecl</tt>,<tt>constMethodDecl</tt>and <tt>classMethodDecl</tt> macros. The class method <tt>new</tt> looks99% of the time like this one, that is calling the allocator and initializingthe new object.<p>Finally, the class implementation is delimited by <tt>CLASS_IMPLEMENTATION</tt>and<tt>ENDOF_IMPLEMENTATION</tt> and inside these tags you find the listof the methods and class methods <b>in the same order as declared in theclass interface</b>. Whatever, the compiler will complain if the orderis not respected (except if two successive methods have the same prototype!).<p>The section <tt>(BASE)OBJECT_IMPLEMENTATION</tt> and <tt>(ABSTRACT)CLASS_IMPLEMENTATION</tt>can be declared at the top of the file if you provide the methods prototypesbefore. It may significantly improve the readability of big implementation.<p>Note: Inside <i>methods and object methods</i>, the <b>current objectis always called<tt>this</tt></b> (C++: member function and <tt>this</tt>pointer). It is a pointer to constant object if the method has been declaredas a constant method (C++: constant member function).<p>Note: If your libc does not provide the non-C89 <tt>strdup()</tt> function,your can use the one provided in <tt>ooc.c</tt> by compiling your programswith the flag <tt>-DALLOW_STRDUP</tt>.<br>&nbsp;<table CELLPADDING=5 COLS=1 WIDTH="100%" BGCOLOR="#66FFFF" NOSAVE ><tr NOSAVE><td NOSAVE><a NAME="Inheritance"></a><b><font face="Arial,Helvetica"><font size=+2>Inheritance</font></font></b></td></tr></table><p>Up to now, we have seen how to define base objects which do not inheritfrom other objects. But without inheritance you cannot reuse already implementedobjects or split your project into smaller entities like OOP requires.Since we need at least another object, we create the specialized subclass<tt>employee</tt>from the class <tt>person</tt>. As in real life, an employee is a personto which we add a departement information. So we derive <tt>employee</tt>from<tt>person</tt>.Person viewed from employee becomes a <i>superclass</i>. Here is the employeeinterface (<tt><a href="examples/employee.h">employee.h</a></tt>):<blockquote><tt>#ifndef EMPLOYEE_H</tt><br><tt>#define EMPLOYEE_H</tt><p><tt>#include &lt;person.h></tt><p><tt>#undef&nbsp; OBJECT</tt><br><tt>#define <b>OBJECT</b> employee</tt><p><b><tt>OBJECT_INTERFACE</tt></b><p><tt>&nbsp; <b>INHERIT_MEMBERS_OF</b> (person);</tt><br><tt>&nbsp; char const* <b>private</b>(department);</tt><p><b><tt>OBJECT_METHODS</tt></b><p><tt>&nbsp; <b>INHERIT_METHODS_OF</b> (person);</tt><p><b><tt>ENDOF_INTERFACE</tt></b><p><b><tt>CLASS_INTERFACE</tt></b><p><tt>&nbsp; t_employee*const <b>classMethod_</b>(new) char const name[],char const department[] __;</tt><br><tt>&nbsp; void <b>method_</b>(init) char const name[], char constdepartment[] __;</tt><br><tt>&nbsp; void <b>method_</b>(copy) t_employee const*const emp __;</tt><p><b><tt>ENDOF_INTERFACE</tt></b><p><tt>#endif</tt></blockquote>The listing above shows how it is simple to derive your class from oneor more superclasses. First you need to include the interface of the superclass.Then you define the class name, the object interface and the class interfaceas we have seen before (see <a href="#Interface">Interface</a>). The inheritanceis built by the declarations <tt>INHERIT_MEMBERS_OF()</tt> and <tt>INHERIT_METHODS_OF()</tt>in the object definition delimited by <tt>OBJECT_INTERFACE</tt> and <tt>OBJECT_METHODS</tt>.Inheritance declaration must always be placed <b>at the beginning</b> ofthese sections. As you can see, the <tt>BASE</tt> prefix disappeared fromthese tags since <tt>employee</tt> is not a <i>base object</i> but a derivedobject.<p>The inheritance declarations in implementation are as simple as forthe interface (<tt><a href="examples/employee.c">employee.c</a></tt>):<blockquote><tt>#include &lt;stdio.h></tt><p><tt>#define <b>IMPLEMENTATION</b></tt><p><tt>#include &lt;employee.h></tt><p><tt>void</tt><br><tt><b>constMethodOvldDecl</b>(print, person)</tt><br><tt>{</tt><br><tt>&nbsp; <b>sendCMsg</b>(<b>this</b>, person, print);</tt><br><tt>&nbsp; /* sub_cast() downcast this from person to employee */</tt><br><tt>&nbsp; printf("\tdept:\t%s\n", <b>sub_cast</b>(this,person)->m.department);</tt><br><tt>}</tt><p><b><tt>OBJECT_IMPLEMENTATION</tt></b><p><tt>&nbsp; <b>SUPERCLASS</b>(person)</tt><p><b><tt>ENDOF_IMPLEMENTATION</tt></b><p><tt><b>initClassDecl</b>() /* class ctor, required */</tt><br><tt>{</tt><br><tt>&nbsp; <b>initSuper</b>(person);</tt><br><tt>&nbsp; <b>overload</b>(person.print) = <b>methodOvldName</b>(print,person);</tt><br><tt>}</tt><p><tt><b>dtorDecl</b>() /* object dtor, required */</tt><br><tt>{</tt><br><tt>&nbsp; person._person(<b>super</b>(<b>this</b>,person)); /* upcast*/</tt><br><tt>&nbsp; free((void*)<b>this</b>->m.department);</tt><br><tt>&nbsp; <b>this</b>->m.department = NULL;</tt><br><tt>}</tt><p><tt>t_employee</tt>

⌨️ 快捷键说明

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