Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 26: Inheriting Multiple Inheritance 349

As an example of the latter, consider a TeacherAssistant who is both a Student and a Teacher, both of which are subclasses of Academician. If the university gives its teaching assistants two IDs — a student ID and a separate teacher ID — the class TeacherAssistant will need to contain two copies of class Academician.

Constructing the Objects

of Multiple Inheritance

The rules for constructing objects need to be expanded to handle multiple inheritance. The constructors are invoked in the following order:

1.First, the constructor for any virtual base classes is called in the order in which the classes are inherited.

2.Then the constructor for all nonvirtual base classes is called in the order in which the classes are inherited.

3.Next, the constructor for all member objects is called in the order in which the member objects appear in the class.

4.Finally, the constructor for the class itself is called.

Notice that base classes are constructed in the order in which they are inher­ ited and not in the order in which they appear on the constructor line.

Voicing a Contrary Opinion

I should point out that not all object-oriented practitioners think that multi­ ple inheritance is a good idea. In addition, many object-oriented languages don’t support multiple inheritance.

Multiple inheritance is not an easy thing for the language to implement. This is mostly the compiler’s problem (or the compiler writer’s problem). But mul­ tiple inheritance adds overhead to the code when compared to single inheri­ tance, and this overhead can become the programmer’s problem.

More importantly, multiple inheritance opens the door to additional errors. First, ambiguities such as those mentioned in the earlier section “Straightening Out Inheritance Ambiguities” pop up. Second, in the presence of multiple inher­ itance, casting a pointer from a subclass to a base class often involves chang­ ing the value of the pointer in sophisticated and mysterious ways. Let me leave the details to the language lawyers and compiler writers.

350 Part V: Optional Features

I suggest that you avoid using multiple inheritance until you’re comfortable with C++. Single inheritance provides enough expressive power to get used to. Later, you can study the manuals until you’re sure that you understand exactly what’s going on when you use multiple inheritance. One exception is the use of commercial libraries such as Microsoft’s Foundation Classes (MFC), which use multiple inheritance quite a bit. These classes have been checked out and are safe.

Don’t get me wrong. I’m not out and out against multiple inheritance. The fact that Microsoft and others use multiple inheritance effectively in their class libraries proves that it can be done. However, multiple inheritance is a fea­ ture that you want to hold off on using until you’re ready for it.

Chapter 27

Tempting C++ Templates

In This Chapter

Examining how templates can be applied to functions

Combining common functions into a single template definition

Defining a template or class

Reviewing the advantages of a template over the more generic “void” approach

The Standard C++ Library provides a set of basic functions. The C++ library presents a complete set of math, time, input/output, and DOS operations, to name just a few. Many of the earlier programs in this book use the so-called

character string functions defined in the include file strings.h. The argument types for many of these functions are fixed. For example, both of the arguments to strcpy(char*, char*) must be a pointer to a null-terminated character string — nothing else makes sense.

There are functions that are applicable to multiple types. Consider the example of the lowly max() function, which returns the maximum of two arguments. The function declarations in Table 27-1 all make sense.

Table 27-1

Possible Variants of maximum() Function

Function Name

 

Operation Performed

maximum(int, int):

Returns the maximum of two integers.

 

 

 

maximum (unsigned

 

Returns the maximum of two unsigned values.

int, unsigned int)

Because there are no negative numbers, the

 

 

expression (0 - 1) “rolls over” to become a very

 

 

large unsigned value, rather than the “normal” or

 

 

signed value –1.

 

 

 

Maximum

 

Performs the same comparison operation but on

(double, double)

 

floating numbers.

 

 

 

Maximum

 

Returns the character that occurs later in the alpha-

(char, char)

 

bet (including all special characters).

352 Part V: Optional Features

I would like to implement maximum() for all four cases. Of course, C++ can pro­ mote all of the types specified into double. Thus, you could argue that the maximum(double, double) version is all that is actually needed. Consider, however, what that would mean to the following expression:

//prototype a max() function double maximum(double, double);

//user function

void fn(int nArg1, int nArg2)

{

int nLarger = (int)maximum((double)nArg1, (double)nArg2);

// ...continue...

}

In this case, both nArg1 and nArg2 must be promoted to double with the accompanying loss of accuracy. This maximum() function returns a double. This value must be demoted from double back to an int via the cast before it can be assigned to nLarger. The function might work without loss of accu­ racy, but the numerous conversions take much more computer time than a silly maximum() function should. In any case, the function doesn’t work the way the user would expect or hope.

Of course, you could overload maximum() with all the possible versions:

double maximum(double d1, double d2)

{

if (d1 > d2)

{

return d1;

}

return d2;

}

int maximum(int n1, int n2)

{

if (n1 > n2)

{

return n1;

}

return n2;

}

char maximum(char c1, char c2)

{

if (c1 > c2)

{

return c1;

}

return c2;

}

// ...repeat for all other numeric types...