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

📄 chapter2.htm

📁 嵌入式软件开发.rar
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<p>
It may seem like double jeproady that the pointer to an instance of the object must be used 
twice in each <a href="chapter1.htm#method">method</a> call.  The first is to get to the individual function, and the second is 
to identify the specific object being worked upon.  If several objects are defined, the 
pointer to the object in the function name can be a pointer to any of the several 
instantiated objects.  Each object will have a pointers  to all object <a href="chapter1.htm#method">method</a>s within the 
object definition.  Every like object will contain these pointers, and their values will all be 
the same.  That is one of the inefficiencies of this approach.  There is the extra baggage of 
pointers to each of the object <a href="chapter1.htm#method">method</a>s contained in each instance of the object.  Each 
object will therefore be somewhat longer than one would think necessary.  We will see in 
the next example, however, that there are benefits to be obtained from this seeming waste 
of memory space.
<p>	A test program is shown below.  In this case, two instances of the object are 
created.  Both of these instances are incremented twelve times, and then the a instance is 
incremented an additional six times.
<pre>
	#include "counter2.h"
	#include &lt;stdio.h&gt;

	main()
	{
	    Count *a=count_();
	    Count *b=count_();
	    int i;
	    
	    for(i=0;i<12;i++)
	    {
	        (*a->increment)(a);
	        (*b->increment)(b);
	    }
	    for(i=0;i<6;i++)
	    {
	        (*a->increment)(a);
	    }
	    printf("a=%d and b=%d\n",(*a->query)(a),(*b->query)(b));
	    count__(a);
	    count__(b);
	}
</pre>
<p>	The output from this program is
<pre>
 
    a=18 and b=12
</pre>
 
<p>
as it should be.
<p>	The above class will be  counter2.   counter2 satisfies the requirements established 
earlier.  It has the ability to be incremented at arbitrary times, and the number of times that 
it was incremented can be determined at any time.  The program can create an arbitrary 
number of counters,  and the interface between the counter and the program is uniform.  
Admittedly, the interface is somewhat different depending upon the type of class that has 
been used, but once this choice has been made, access to each of the <a href="chapter1.htm#method">method</a>s associated 
with the class is uniform.  In the final version, the <a href="chapter1.htm#method">method</a> names are hidden within the 
scope of the file in which they are created.  Therefore, there can be several objects that 
have the same <a href="chapter1.htm#method">method</a> names, and there will be no name conflicts in the program.  The 
version called counter1 will not afford this benefit.  In that case, the <a href="chapter1.htm#method">method</a> names are 
global and it is easily possible to have name conflicts with different classes in the program.  
As mentioned above, the price associated with this <a href="chapter1.htm#method">method</a> name hiding is that each object 
must contain pointers to each of the class <a href="chapter1.htm#method">method</a>s making the size of the object larger 
than with the approach used in counter1.  There is, however, an additional benefit beyond 
name hiding.  That benefit is that with the <a href="chapter1.htm#method">method</a> used in counter2, it is possible to 
implement <a href="chapter1.htm#inheritance">inheritance</a>.
<p>	The class counter is a simple recording counter that can be incremented and 
queried to determine the number of increments.  Suppose that we need to expand the 
capabilities of our counter to allow not only increment and query, but also decrement.  
There is a very important distinction at this point.  This class and the objects instantiated 
are counters.  The basic nature of the operation of the class is unchanged.  If we call this 
sysem an up/down counter, we can say without fear of contridiction that up/down counter 
is a counter.  If a program is to use <a href="chapter1.htm#inheritance">inheritance</a>, the programmer must be able to say that 
the class inherited from the super class is of the same basic nature as the super class.  
Otherwise, a different programming approach probably should be used.  Since an up/down 
counter is a counter, we are safe to conculde that up/down counter can inherit the 
characteristics of counter and we will see a classic case of  class <a href="chapter1.htm#inheritance">inheritance</a>.
<p> The <a href="chapter1.htm#header">header file</a> for the up/down counter is shown below.  The up/down counter is 
to be inherited from counter2, so counter2.h must be included in the <a href="chapter1.htm#header">header file</a>.  Recall 
that in counter2.h, a define statement defined COUNT which contained all of the 
<a href="chapter1.htm#attribute">attribute</a>s and <a href="chapter1.htm#method">method</a>s needed to implement that version of the counter.  In this header, 
new structure members are defined for the up/down count.  First of all, the members of 
COUNT  are included in the definition of UDCOUNT.  Additionally, the function 
prototype for the decrement function is included in the definition.  UDCOUNT defines all 
of the <a href="chapter1.htm#attribute">attribute</a>s and <a href="chapter1.htm#method">method</a>s of COUNT along with the new decrement function.  This 
define statement is then used as the argument of the struct udcount which is typedefed as 
the new type Udcount.  This is our new class and the <a href="chapter1.htm#header">header file</a> is saved in counter3.h.
<pre>
 
	#ifndef UDCOUNT_H
	#define UDCOUNT_H

	#include "defines.h"
	#include "counter2.h"

	#define UDCOUNT \
	    COUNT \
	    void (*decrement)(struct udcount *);

	typedef struct udcount
	{
	    UDCOUNT
	}Udcount;                                                        

	Udcount *udcount_(void);
	void udcount__(Udcount *);

	#endif
</pre>
 
<p>  The functions increment() and query() used in the definition of counter2 are still valid 
functions for this class.  Therefore, the new class must define only the function 
decrement().  decrement() is the first function defined in the <a href="chapter1.htm#implementation_file">implementation file</a>. 
<p>	The <a href="chapter1.htm#constructor">constructor</a> is somewhat different from that in counter2.  The <a href="chapter1.htm#attribute">attribute</a>s and 
<a href="chapter1.htm#method">method</a>s of an instance of Count as defined by counter2 are use as a base class to udcount. 
A temporary instance of an object Count will be created by execution of the count_() 
<a href="chapter1.htm#constructor">constructor</a>.  Dynamic allocation is used via malloc() to create a memory space large 
enough to hold our new Udcount object.  The contents of the temporary Count object are 
then moved onto the newly created Udcount object, and then the temporary Count is 
deleted by execution of its <a href="chapter1.htm#destructor">destructor</a>.  Finally a pointer to the function decrement is 
placed in the proper location in the object, and a pointer to the new object is returned to 
the calling program.  Pointers to incerment() and query() will be contained in the object 
created by the <a href="chapter1.htm#constructor">constructor</a> count_().  Therefore, these <a href="chapter1.htm#method">method</a>s from the base class will be 
used as <a href="chapter1.htm#method">method</a>s for Udcount.  Also, count_() initializes the count to zero, so when an 
object of the type Udcount is instantiated, it will have its own version of decrement() and 
will share the code from Count for increment() and query().  This new object will also 
have its own location count in which the number of increments less the decrements is 
stored.  
<pre>
 
	#include "counter3.h"
	#include &lt;stdlib.h&gt;    /* for memory function access */

	static void decrement(Udcount *this)
	{
	    this->count--;
	}

	Udcount *udcount_(void)
	{
	    Udcount *this;
	    Count *temp=count_();
	    
	    if((this=(Udcount *)malloc(sizeof(Udcount)))==NULL)
		  error_handler();
	    memmove(this,temp,sizeof(Count));
	    count__(temp);
	    this->decrement=decrement;
	    return this;
	}

	void udcount__(Udcount *this)
	{
	    free(this);
	}
</pre>
 
<p> The test function shown below demonstrates all operations of Udcount.  Two 
instances of Udcount are instantiated.  These instances are a and b.  Both instances are 
incremented twelve times, and the values of the results are printed out.  Then a is 
incremented an additional six times while b is decremented six times.
<pre>
 
	#include "counter3.h"
	#include &lt;stdio.h&gt;

	main()
	{
	    Udcount *a=udcount_();
	    Udcount *b=udcount_();
	    int i;
	    
	    for(i=0;i<12;i++)
	    {
	    		(*a->increment)(a);
	    		(*b->increment)(b);
	    }
	    printf("a=%d and b=%d\n",(*a->query)(a),(*b->query)(b));
	    for(i=0;i<6;i++)
	    {
		   (*a->increment)(a);
		   (*b->decrement)(b);
	    }
	    printf("a=%d and b=%d\n",(*a->query)(a),(*b->query)(b));
	    udcount__(a);
	    udcount__(b);
	    return 0;
	}
</pre>
 
<p>	The output from this program is as follows:
<pre>
 
	a=12 and b=12
	a=18 and b=6
</pre>
 
<p>
which is the expected results.  Here Udcount has inherited all of the <a href="chapter1.htm#method">method</a>s and 
<a href="chapter1.htm#attribute">attribute</a>s of Count and extends the operation of the object to include a decrement as well 
as the increment and query associated with Count.  Actually, one could have created a 
Udcount with all of the necessary <a href="chapter1.htm#method">method</a>s.  However, this approach could require more 
code than is needed above because, in a program where both Count and Udcount are 
needed, the code for the <a href="chapter1.htm#method">method</a>s in Count would not need to be repeated for Udcount.  
This ability to share code is one of the important benefits found with <a href="chapter1.htm#inheritance">inheritance</a>.  
Additionally, Udcount is another instance of a counter, and it is used in much the same 
way as Count.  We have been able to build onto a base class another class that has all of 
the base class characteristics with some new characteristics of its own.

<h2><a name="polymorphism"><a href="chapter1.htm#polymorphism">Polymorphism and Virtual Functions</a></a></h2>

	With the above background, both <a href="chapter1.htm#polymorphism">polymorphism</a> and virtual functions written in C 
can be examined.  The basic idea of <a href="chapter1.htm#polymorphism">polymorphism</a> is to allow several functions that 
execute similar but different functions for different inherited classes to have the same 
name.  The choice as to which function will be used by the different classes cannot be 
made at the time of linking.  This choice must be made when the program is run.  Thus, 
the name late binding or run-time linking is also assigned to <a href="chapter1.htm#polymorphism">polymorphism</a>.  It should be 
noted that a virtual funcion is in not really bound at run time.  In reality, the means by 
which a virtual function is created is to use a level of indirection in the choice of a function 
to be executed.  Therefore, all of the functions referred to as virtual are really accessed by 
pointers to the specific function to be executed rather than by the function name.  Let us 
examine this concept further in the following discussion.
<p>	We begin by defining a class Graph that in essence defines a point.  However, this 
class is really a dummy class that will never be instantiated with a regular program. Such a 
class is called an abstract class; the purpose of this type of class is to be a parent or a 
superclass which will be used to inerhit other useful classes.  Consider the class shown 
below.
<pre>
 
	#ifndef GRAPH_H
	#define GRAPH_H
	#include "defines.h"
	    
	/* elements and methods of the class graph */
	#define GRAPH_CLASS\
	    int     x,\
	            y,\
	            background, \
	            foreground; \
	    Boolean visible,\
	            (* is_visible)(struct graph*);\
	    void    (* show)(struct graph*),\
	            (* hide)(struct graph*),\
	            (* move)(struct graph*, int, int);

	typedef struct graph
	{
	    GRAPH_CLASS
	} Graph;

	Graph* graph_(int x,int y,int background,int foreground); 

	void graph__(Graph*);

	#endif
</pre>
 
<p>
GRAPH_CLASS is defined and contains all of the members of the class Graph.  The 
struct graph members then is the single statement GRAPH_CLASS.  The above class 
definition will be saved in a file graph.h.  
<p>	It is not necessary to include  parameter names in a function prototype as was done 
above.  In the prototypes for the <a href="chapter1.htm#constructor">constructor</a>s there are frequently several parameters, and 
it is a good idea to include some type of descriptive names for each of the parameters.  For 
example, in the above case, x and y are the coordinates of the graphics point.  The 
parameter background is the background color and foreground is the foreground color.  
With these parameters named in the <a href="chapter1.htm#constructor">constructor</a> prototype, is not necessary to examine the 
<a href="chapter1.htm#implementation_file">implementation file</a> to determine the meanings of these several parameters.
<p>	The <a href="chapter1.htm#implementation_file">implementation file</a> for this class is shown below.  We include the file graph.h 
to make available to the program all of the information shown above.  The <a href="chapter1.htm#constructor">constructor</a> and 
<a href="chapter1.htm#destructor">destructor</a> programs shown later are a part of this file.  The code has been moved here to 
keep the descriptive text near-by the code.  With this version of  object  management, it is 
necessary to pass a pointer to the specific instantiation of an object to each <a href="chapter1.htm#method">method</a> 
whenever a <a href="chapter1.htm#method">method</a> is called.  Therefore, you will note below that the first argument of 
each <a href="chapter1.htm#method">method</a> is a pointer to a type Graph.  This pointer selects the specific object that the 

⌨️ 快捷键说明

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