📄 chapter2.htm
字号:
<head>
<title>Chapter 2 Object Oriented Programming in C</title>
</head>
<body>
<h1>Object Oriented Programming in C</h1>
<h4>Special Heading For HTML Version</h4>
<strong><p>This Chapter contains links to the definitions of each new Object Oriented
Programming word. There may seem to be an excessive number of links to the same
location. However, anyone reading this chapter who sees an unusual word anywhere in
the text will be able to jump to its definition with a point and click.</strong>
<p>
Why would we want to do object oriented programming in C? There is one
overwhelming reason that we cannot overlook. Today, there are no C++ compilers for
our microcontrollers! The only approach to use C++ is to compile the C++ program with
a cfront. A cfront is a compiler that compiles C++ code into C code. The resultant code
can be then compiled with a C compiler. A cfront will produce code aimed to be used on
a large computer, and it is not too forgiving of the many tricks that are usually employed
in C to permit the code to run on a microcontroller. Therefore, a clear alternative to
writing code in C++ is to write object oriented code in C. In many cases, C can do the
same job as C++. There are clearly some features of C++ that must be lost when C is
used to code OOP. Recall the three key words of OOP are <a href="chapter1.htm#encapsulation">encapsulation</a>, <a href="chapter1.htm#inheritance">inheritance</a>, and
<a href="chapter1.htm#polymorphism">polymorphism</a>. With only a few compromizes,OOP code in C retains most of these
capabilities. The features that are lost are both operator and function overloading and the
protection modes of C++. We will see several examples of object oriented programming in
C and will examine the costs of doing our business in this language. Some features are
completely lost, some are impared, but many are still available and can be used to great
advantage without the need for a C++ compiler.
<h2><a name="classes"><a href="chapter1.htm#class">Classes</a>,
<a href="chapter1.htm#object">Objects</a> and <a href="chapter1.htm#encapsulation">Encapsulation</a></a></h2>
<p>
An object is usually considered a memory storage location. It will still be true in
OOP written in C. In Chapter 1, we saw a class which was described as an object
template. Here we will use the structure to create our object template. To begin, we will
use a structure that contains all of the necessary data for the object. Associated with the
object are the several functions needed to manipulate the <a href="chapter1.htm#attribute">attribute</a>s of the object. Let us
choose a very simple object that we can explore easily. The object in this case is going to
be a counter. The counter has only one <a href="chapter1.htm#attribute">attribute</a>: the number of the count. This counter
will work like a hand held counter used by a theater usher who counts the number of
people entering a theater. The counter content can be incremented and it may be read.
The <a href="chapter1.htm#attribute">attribute</a> is the count, and there are two <a href="chapter1.htm#method">method</a>s associated with the counter:
increment and query.
<p>
Shown below is a <a href="chapter1.htm#header">header file</a> named defines.h. This file is short and requires little
explanation here. Several of the important defined constants needed in our programs are
identified here, and the <a href="appendxb.htm#defines">defines.h</a> header can be included at the beginning of each file to
create these definitions for each program module.
<p>
<pre>
#ifndef DEFINES_H
#define DEFINES_H
#ifndef NULL
#define NULL (void *)0
#endif
#define EOM 0
#define FOREVER while(TRUE)
typedef int Boolean;
typedef unsigned int WORD;
typedef unsigned char BYTE;
enum {FALSE,TRUE};
enum {OFF,ON};
enum {NO,YES};
enum {FAST,SLOW};
enum errors
{
SEMAPHORE,
SERIAL,
TIMER,
DELAY,
PWM
};
enum edges
{
DISABLE,
RISING,
FALLING,
ANY
};
enum outputs
{
DISCONNECT,
TOGGLE,
CLEAR,
SET
};
#endif
</pre>
<p> Note that the header starts with two lines
<pre>
#ifndef DEFINES_H
#define DEFINES_H
</pre>
<p>
Also note that the last line of the file is
<pre>
#endif
</pre>
These simple commands will cause any multiple inclusion of this file to be ignored.
Therefore, there will be no multiple definitions of symbols found in the file regardless of
the number of times that the file is included in different modules when the program is
compiled. All <a href="chapter1.htm#header">header file</a>s should be protected from multiple inclusion by this simple
mechanism. Most of the remainder of the defines.h <a href="chapter1.htm#header">header file</a> contents is self explanatory.
The parameter NULL is not defined by the language. We define it here as a pointer to a
type void, and the pointer has a zero value. This definition is protected by an #ifndef test
to assure that there is no more than one inclusion of the definition for a NULL in a
program. The macro FOREVER is very useful in most main programs for embedded
systems. There are several enumerates that are convenient to simply define, and assign
values to constant names needed through the book. The various items enumerated and
macros defined are needed in typical programs. The enumeration that defines SERIAL,
TIMER, etc. is needed for the system error handler that will be discussed in Chapter 4.
The enumerations edges and outputs contain values helpful in writing code for the input
caputre system and the output compare system.
<p>
Shown below is the <a href="chapter1.htm#header">header file</a> for our simple counter.
This <a href="chapter1.htm#header">header file</a> contains
the protection from multiple inclusions and an include command to include the defines.h
header in the program. Next, the header contains a typedef command for a structure type.
The structure type has no tag name, but the structure is given a type name Counter. This
structure contains only one member called count. count is of the type WORD which is
identified by a typedef command in defines.h as an unsigned int.
<pre>
#ifndef COUNTER_H
#define COUNTER_H
#include "defines.h"
struct
{
WORD count;
}Counter;
void increment(void);
int query(void);
#endif
</pre>
<p>
Also found in the <a href="chapter1.htm#header">header file</a> are two function prototypes. You will note that there
is no function code for these functions in the <a href="chapter1.htm#header">header file</a>. In OOP talk, this file is called the
class <a href="chapter1.htm#header">header file</a>. Such files should never contain executable code. All executable code
associated with a class is included in the class <a href="chapter1.htm#implementation_file">implementation</a> file.
The class
<a href="chapter1.htm#implementation_file">implementation file</a> for our counter class is shown below. The <a href="chapter1.htm#header">header file</a> that contains the
above header is called counter0.h.
<pre>
#include "counter0.h"
void increment(void)
{
Counter.count++;
}
int query(void)
{
return Counter.count;
}
</pre>
<p>
The <a href="chapter1.htm#implementation_file">implementation file</a> first includes the appropriate <a href="chapter1.htm#header">header file</a>. The remainder of
the code found in this file is executable code. The two functions found here are
increment() and query(). Recall that these function prototypes are included in the header
file. This particular program structure follows C++ closely. If the programmer wishes to
build a library of objects, it is possible to deliver to a customer a readable version of the
<a href="chapter1.htm#header">header file</a>s and a compiled version of the <a href="chapter1.htm#implementation_file">implementation file</a>s. The way the objects can
be used can be seen from the contents of the <a href="chapter1.htm#header">header file</a>, and the details of how the
objects work are hidden in the <a href="chapter1.htm#implementation_file">implementation file</a>. Therefore, the programmer can sell
the product with assurance that the program details are hidden from the user.
<p>
The two functions in this case perform simple actions. increment() causes the
member count in the object Counter to be incremented, and query() returns the value of
the member count to the calling program. A program that will test the performance of this
object is shown below.
<pre>
#include "counter0.h"
#include <stdio.h>
main()
{
int i;
for(i=0;i<12;i++)
increment();
printf("a=%d \n",query());
}
</pre>
<p>
In this program, it is assumed that counter0.c has been compiled and the compiled version
is linked with the above program when it is compiled. The result of execution of this
program is
<pre>
a=12
</pre>
<p>
as expected.
<p>
Let us examine this program in a little more detail to determine what we have and
have not accomplished. First of all, Counter is an object. From an <a href="chapter1.htm#encapsulation">
encapsulation </a>
standpoint, counter does not meet the test. The <a href="chapter1.htm#attribute">attribute</a> count is accessed by the class
<a href="chapter1.htm#method">method</a>s. There is, however, no mechanism that prevents any portion of the program from
accessing count once the object has been created. This portion of <a href="chapter1.htm#encapsulation">encapsulation</a>, <a href="chapter1.htm#attribute">attribute</a>
hiding, is not a part of and cannot be easily implemented by C. All programmers must
agree to access object <a href="chapter1.htm#attribute">attribute</a>s through the <a href="chapter1.htm#method">method</a>s provided with the class only
<p> Additionally, there is another difficulty. One would expect that the programmer
should be able to create several instances of the object Counter. On the contrary, Counter
in this case is in itself an instance of a structure, and no mechanism is avaliable for creating
additional instances. You will observe that the two <a href="chapter1.htm#method">method</a>s increment() and query() both
operate on the member count in the structure Counter. If other versions of Counter were
available, increment() and query() would have no means for accessing these other
instances. To be practical, it is necessary that our class approach allow the instantiation of
several different instances of Counter, and the <a href="chapter1.htm#method">method</a>s must access the individual instance
that the programmer needs.
<p> These problems are easily addressed. The <a href="chapter1.htm#method">method</a>s will each have an argument
that is a pointer to the individual object that is being accessed. A <a href="chapter1.htm#header">header file</a> for the class
Counter that implements this approach is shown below. Note here that a typedef
construct is used to create the type Counter. This type contains only one WORD member.
The function prototypes for both increment() and query() now contain arguments that are
pointers to the type Counter. When using this approach, we need a means to create an
instance of Counter, or a pointer to the type Counter, and delete a specified instance. The
function count_()--single underscore--is the <a href="chapter1.htm#constructor">constructor</a>
for the object Counter. This
function will create an instance of Counter and return a pointer to that specific instance to
the calling program. The <a href="chapter1.htm#destructor">destructor</a> is count__(), double
underscore. This function is
executed with an argument that is a pointer returned from count_(). The <a href="chapter1.htm#destructor">destructor</a> will
destroy the specific instance of Count. We shall append a single underscore to the name
of a <a href="chapter1.htm#constructor">constructor</a> and a double underscore to the name of a <a href="chapter1.htm#destructor">destructor</a> throughout this text.
<pre>
#ifndef COUNTER_H
#define COUNTER_H
#include "defines.h"
typedef struct
{
WORD count;
}Counter;
void increment(Counter *);
int query(Counter *);
Counter *counter_(void);
void counter__(Counter *);
#endif
</pre>
<p>
Both of these functions exist in C++. Either can be defined as we will do here, or the
language provides a default version of both the <a href="chapter1.htm#destructor">destructor</a> and the <a href="chapter1.htm#constructor">constructor</a>. C requires
that the program provide the <a href="chapter1.htm#constructor">constructor</a> and <a href="chapter1.htm#destructor">destructor</a>. It is important that the program
create each object when it is needed, and it is equally important that the object be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -