Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006)

.pdf
Скачиваний:
192
Добавлен:
12.08.2013
Размер:
3.18 Mб
Скачать

62 4 THE OBJECT-ORIENTED APPROACH

Each object class will have its own name, also known as the object type name. The word class is a keyword in C++. It is used to identify a detailed plan with a name. Programmers are free to choose class names when developing new classes.

Each object class must have a class definition. Similar to the case for real-life objects, the properties or features of the object and the functions associated with the object are listed in its class definition. The properties or features are given the name member data of the class and the functions associated with the object are referred to as member functions.

Among the member functions are two special types of functions. The first type can have more than one function per class and are known as constructors. Constructors are used by the program to create each individual object (that resides in memory). The second type has only one function per class and is known as a destructor. Destructors are used by the program to free the memory that a variable used once the variable is no longer needed. If a constructor is not provided, the C++ compiler will provide a default constructor (invisible to the programmer). Similarly, if a destructor is not provided, the C++ compiler will add a default destructor (also invisible to the programmer).

Private:

Member Data

Member Functions

Protected:

Member Data

Member Functions

Public:

Interface to Outside

Member Data Program Code

Member Functions

Figure 4-4 Public interface of an object class .

Some of the class members (both data and functions) can be publicly accessed; other members will have restricted access. The publicly accessible members provide the public interface of the object as shown in Figure 4-4. These include the public member data and public member functions. Members with more restricted access are known to have either private or protected access attributes.

4 THE OBJECT-ORIENTED APPROACH 63

4.5 Encapsulation

Grouping the member data and member functions together is known as encapsulation. There are some great benefits associated with encapsulation. First of all, encapsulation limits access to the internal details of the object. Access to the data is always through controlled and supervised means. In general, access will be restricted to most data members where data should not be freely accessible or changeable. Some of the functions may also have restricted access.

Access to the object is allowed only through the public interface. This ‘restricted visibility’ to member data and member functions is also known as information hiding. Sometimes it is not necessary to know the internal details of an object. In this case it is often sufficient to just be able to know how to use it. A good example is a scroll bar. It is sufficient for the programmer to know how to place a scroll bar in an application to make the screen scroll. The scroll bar’s internal workings are hidden and normally are of no concernt to the programmer.

While all these restrictions are imposed to functions outside of the class, internally, any function of the class can manipulate or access any other member of the same class. This provides efficient operation of object-oriented programs for the following reasons. It eliminates the need to declare member data within the functions and also the need to pass member data as parameters to member functions. While an ordinary non-member function can only return one value, the member functions can return ‘more than one value’ by being able to change any number of the data members of the class.

4.5.1 Object Instantiation

The process of creating an actual object is known as object instantiation. Therefore, to instantiate an object of a particular class, one of the constructors of that class must be called. The constructor resembles “the manufacturing process” in our ‘car’ analogy. The constructor, like any other function is a function written in C++. It must be called to create a physical object of the object class. While the object class is of type ‘Car’, the actual objects created, which we refer to as class objects, could be named A, B, C, etc. They are all equivalent, perhaps with minor differences like their colour. In object-oriented programming, a class definition does not occupy memory. However, a class object does occupy memory. Likewise a building plan does not occupy any land, whereas the actual building occupies finite space.

In object-oriented programming, the constructor must be called to create an actual object. At the time of calling the constructor, you can pass parameters to it in a likeness to selecting the colour of a car to be built. In a class definition, there may be more than one constructor. In our car analogy, a car may be constructed from scratch or may be constructed from subassemblies.

64 4 THE OBJECT-ORIENTED APPROACH

4.6 Abstract Classes

Abstract classes can be viewed as initial conceptual class definitions which are insufficiently complete to carry out instantiation. Many good hierarchies of class objects will often start with an abstract class. The real power of abstract classes cannot be properly demonstrated until some advanced concepts of the C++ language are explained in the coming chapters.

An abstract class needs to be developed to become a real class that has working functions if it is to be able to instantiate real objects and use them. There is no such thing as ‘an abstract object’ for the simple reason that anything abstract does not physically exist. In our ‘vehicle’ example, there will definitely be a characteristic such as speed. However, we cannot discuss how to increase or decrease speed until we know more details of the actual vehicle. We can also include ‘functions’ to increase and decrease the value of the speed. However, we cannot define the exact steps these ‘functions’ should take to increase or decrease the speed without knowing whether the vehicle is a car, or a train, or something else. In an analogous class definition, these types of functions are known as pure virtual functions. They are pure because their actions (bodies) cannot be defined yet, and virtual because their actions (bodies) need to be defined in future derived classes to carry out their required tasks.

4.7 Class Hierarchies

A class hierarchy is a set of classes that are developed starting from one or more classes known as base classes (located at the root of the hierarchy). The new classes developed from the base classes are known as derived classes. The derived classes are more detailed and complete than their base classes. One of the most important benefits of object-oriented programming is code reuse. Developing class object hierarchies greatly facilitates the ability to reuse code by not having to rewrite code that new code is based on. Object-oriented programming allows us to re-use already written code as often as we like.

The base class can be an abstract class, although this is not an essential requirement. As mentioned earlier, no real object can be instantiated from an abstract class. However, it is useful to form a general abstract base class by including the essential member data and member functions that will be common to all objects of the derived classes of the hierarchy.

As an example, if you consider a graphics program which works with geometric shapes such as lines, circles, triangles, squares, etc; a base class definition can be formed to move, scale, hide, show, stretch any of these objects. Let us call this class the Shape class. The class that we form, without referring to a specific object, can be an abstract class. As mentioned above, base classes do not need to be abstract classes. The abstract class will define the functionality of all objects of the hierarchy without specifying a particular object type.

4 THE OBJECT-ORIENTED APPROACH 65

The derived classes must be more specific than the abstract class. For example, there can be a derived class, which specifically works with a circle. Let us name this the Circles class. Then, all functions within the Circles class such as Move, Scale, Hide, Show, and Stretch can be coded specifically to operate on circle objects. As you can imagine, it is very difficult to transfer the functionality of the Circles class over to a new class named Squares to work with squares! You will need to make so many changes to be able to operate with squares in place of circles. It is easier to directly derive the Squares class from the abstract class Shape, and then define the functions the Squares class needs. Although the abstract classes cannot be used to instantiate new objects, they have a very powerful use associated with virtual functions and late binding. We will discuss these two concepts in Chapter 8.

4.8 Inheritance

Inheritance is closely associated with class hierarchies. When a new object class is derived from a base class, the new class is said to inherit all the member data and member functions of the base class. This is the mechanism that underlies code reuse. The functions and data of the base class automatically exist in the derived class. They do not need to be written again. To provide the new class with functionality beyond that of the base class, we only need to add whatever additional data and functions are necessary. It is also possible to modify the inherited functions to suit their more specific tasks. However, there may need to be restrictions for access to some inherited data and functions.

Shape

Show

Hide

(Abstract Base Class)

etc

 

Circles

Squares

Triangles

Show

Show

Show

Hide

Hide

Hide

etc

etc

etc

Figure 4-5 Inheriting from an abstract class.

As an example, consider the graphics program we mentioned earlier. We discussed an abstract class named Shape. In that class we had graphics functions such as Move, Scale, Show, Hide, Stretch, etc. If we need a new class to specifically work with circles, then we can use the abstract class Shape as the base class and

66 4 THE OBJECT-ORIENTED APPROACH

derive the new Circles class from it. The derived class Circles is said to be a sub-class of the abstract class Shape and will inherit all its functions (and data if it had any). The Shape class does not have properties specific to a circle object such as centre and radius. These properties will be added as new member data to the derived class.

4.9 Multiple Inheritance

It is also possible for a derived class to have more than one base class. In this case the derived class will inherit all the member data and member functions of all the base classes. For example, we can have a base class named Colours, which allows us to set foreground and background colours, choose fill patterns, and carry out filling. We can use the Shape class and the Colours class to derive our new object class Circles (as shown in Figure 4-6). Now the Circles class can be made to show colourful circles on the screen!

Shape

Colours

(Abstract Base Class)

(Base Class)

Circles

Figure 4-6 Multiple inheritance.

4.10 Polymorphism

In principle, object-oriented concepts are profoundly based on the mechanisms of encapsulation, inheritance, and polymorphism. Polymorphism is a more complex concept than the concepts of encapsulation and inheritance which have already been briefly explained.

As applied to object-oriented programming, polymorphism means the existence of a function with the same name, same return value type, same number of parameters and the same type of parameters in a number of classes of the same hierarchy. The bodies of the functions will differ to suit the requirements for each class. It is not essential for every object in the hierarchy to have this function. Furthermore, there can be any number of polymorph functions in a given hierarchy. Polymorphism allows a common interface for related actions. The most powerful feature of object-oriented programming is associated with polymorphism of virtual functions (discussed in Chapter 8).

4 THE OBJECT-ORIENTED APPROACH 67

Let us consider an example of polymorph functions. Since a polymorph function is the ‘same’ function throughout the hierarchy, one would imagine that it carries out the same task in each class. Going back to our graphics example, we can consider Show to be a polymorph function. The function Show is in the Shape class, in the Circles class, in the Squares class, and so forth. Another polymorph function is Hide. Suppose the Show function makes the object visible on the screen. If we are using the Show function with a circle object, it will show a circle. If it is used with a square object, it will show a square. Therefore, although the function name is the same, it operates in a context-sensitive manner according to the type of object it is working with.

Polymorphism is the key to harnessing the great benefits of virtual functions. It is possible for a programmer to use a virtual function in a program without knowing which object it will be used with at run-time (when the program is executing). The program will be written generically to suit all classes of the hierarchy. The programmer does not need to write the complex logic for selecting the correct function to suit the object chosen by the user at run-time. This task is passed on to the compiler and linker, simplifying the programming task immensely. This is of most benefit for programs with large numbers of classes and complex hierarchies.

As an example, a programmer can write a generic program in which the virtual function Show is used to show any object in the hierarchy. The user of the program decides at run time, the actual object the function Show will operate on. The programmer has not needed to develop the full range of complex logic needed to handle whatever type of object from the shape class the user will choose at a particular time. Nonetheless, the correct Show function for that object type will automatically be selected during program operation. This concept will be demonstrated in detail in Chapter 8.

4.11 An Example Object Hierarchy

To enable you to relate some of the concepts described previously, we will develop an object hierarchy without using C++ language syntax or its keywords. The class definitions shown below cannot be compiled in an actual C++ program, however, they demonstrate the principles associated with an object hierarchy. We start with the abstract class Vehicle discussed earlier:

Abstract Class Vehicle

Member data:

Speed

Power

Member Functions:

Stop

Go

68 4 THE OBJECT-ORIENTED APPROACH

This class is the most fundamental of all classes of this example. It has encapsulated the bare minimum that is essential for a vehicle. It must possess Power for it to be able to move, and also will have a Speed characteristic to describe its motion. The member function Go will start the vehicle moving, and the other member function Stop will bring it to a stand-still.

New classes with more specific details added to them can then be derived from the Vehicle class. We have done this by forming two new class definitions named

Passenger Transport, and Goods Transport. This class hierarchy is shown in Figure 4-7 where there are two branches coming from its root (base class). The class definitions are shown below:

Derived Class Passenger Transport: derived from Vehicle class

Additional member data:

Number of Passengers

Derived Class Goods Transport: derived from Vehicle class

Additional member data:

Load carrying capacity in Kg.

Note that these two classes inherit all the member data and member functions of the base class Vehicle. For example, if we list everything in the Passenger Transport class we will form the class definition show below:

Derived Class Passenger Transport

Member data:

Speed

Power

Number of Passengers

Member Functions:

Stop

Go

Vehicle

(Base Class)

Goods

Passenger

Transport

Transport

Figure 4-7 Deriving classes from a base class.

4 THE OBJECT-ORIENTED APPROACH 69

Although we did not specifically mention Speed, Power, Stop and Go, they are present in the new derived class as a result of inheritance. Furthermore, the Goods Transport class is a direct descendant of just the abstract class Vehicle and therefore does not inherit anything from the Passenger Transport class.

Therefore, there are two branches, right at the root of this object hierarchy as shown in Figure 4-7.Also, the Passenger Transport class and the Goods Transport class may or may not be abstract classes. Any of these classes can be used to further derive new classes with additional refinements.

In the next class definition, a new class named Passenger Train is derived from the Passenger Transport base class:

Derived Class Passenger Train: derived from Passenger Transport class

Additional member data:

Number of passenger cars

Additional member functions:

Doors Open

Doors Close

Air Conditioning

In this class definition, the members of the Passenger Transport class are in effect added to the already existing members of the Passenger Transport class that have been inherited (and are invisible). If we managed to see the equivalent complete class definition for the Passenger Train class, it would appear as follows - the inherited members are shown in bold italic typeface:

Derived Class Passenger Train

Member data:

Speed

Power

Number of Passengers

Number of passenger cars

Member Functions:

Stop

Go

Doors Open

Doors Close

Air Conditioning

Just as we used Passenger Transport as a base class, the Goods Transport class can be used to derive further classes. An example of a new Goods Train class derived from the Goods Transport class is now given:

70 4 THE OBJECT-ORIENTED APPROACH

Derived Class Goods Train: derived from Goods Transport class

Additional member data:

Number of boxcars

Number of tank cars

Number of open cars

Motorcars are primarily meant for transporting passengers. Therefore, if we wish to form a new class to represent motorcars, the best place to start is the Passenger Transport class. An example class definition for the new Motorcar class is now given:

Derived Class Motorcar: derived from Passenger Transport class

Additional member data:

Engine Capacity

Body Colour

Trim Colour

Number of Cylinders

Wheel Size

Number of Doors

Additional member functions:

Steer

Brake

If we then need a class definition to represent luxury cars, the best starting point is the Motorcar class. The Motorcar class is chosen instead of the Passenger Transport class because Motorcar objects form a more complete sub-object of a Luxury Car class. If we use the Passenger Transport class as the base class of the Luxury Car class, we will have to re-introduce members such as Engine Capacity, Body Colour, Trim Colour, etc. This involves a lot of unnecessary work, is error prone, and does not take advantage of code reuse.

Derived Class Luxury Car: derived from Motor Car class

Additional member data:

Inside Air temperature

Global Position

Additional member functions:

Air Conditioning Control

Power Mirror Control

Power Window control

Cruise Control

Antenna Control

CD Control

4 THE OBJECT-ORIENTED APPROACH 71

In a class hierarchy, future changes that need to be carried out can be done with minimum reprogramming. If the necessary changes are very specific, then the changes are more likely to be made in the most recently derived classes. If the required changes are more general in nature, it is most likely that the changes will be carried out closer to the root of the hierarchy. For example, if all luxury cars are to have automatic navigation in the future, we will add a new member function named Navigate to the Luxury Car class. On the other hand, if all vehicles are to be fitted with automatic navigation facilities in the future, we will add the Navigate member function to the abstract class Vehicle.

Vehicle

(Base Class)

Goods

 

Passenger

Transport

 

Transport

Goods

Motor

Passenger

Train

Car

Train

 

Luxury

 

 

Car

 

Figure 4-8 The example class hierarchy.

A set of object classes that fit into a class hierarchy always has an expansive nature rather than a multiplicity nature. In an expansive situation, additional member data and member functions will be added to the new derived class. In a multiplicity situation more members of the same object type are added to the new class.

For example, an object class representing a house and another object class representing a better house fit nicely into a class hierarchy. On the contrary, the class representing a house and another class representing many houses of the same type as the other class do not fit into a class hierarchy. New, completely different member objects need to exist in the new class.

Although you may have understood how classes are formed, their use may still be unclear. In the coming chapters, we will develop classes and begin to use them. For now, it is important to gain an understanding of what a class hierarchy is and how it is formed.