Issue #005
January, 1996


Contents:

Web Glossary
New Fundamental Type in C++ - bool
Using C++ as a Better C Part 5 - Function Overloading
Book Review - The Mythical Man Month
Example C++ Class - Mean and Standard Deviation


WEB C++ GLOSSARY

I have put up a glossary of C++ terms on the Web.  The address is:

        http://www.rmii.com/~glenm

Please let me know if you have suggestions for additional terms to be
added to the list.


NEW FUNDAMENTAL TYPE IN C++ - BOOL

A new fundamental (builtin) type has recently been added to C++.  It
is a type for representing Boolean values and uses the keyword
"bool".  For example, you could say:

        bool b;

        b = true;
        if (b)
                ...

A bool value is either true or false.  A bool value can be converted
to an integer:

        bool b;
        int i;

        b = false;
        i = int(b);

in which case false turns into 0 and true into 1.  This process goes
under the C/C++ name of "integral promotion".

A pointer, integer, or enumeration can be converted to a bool.  A null
pointer or zero value becomes false, while any other value becomes
true.  Such conversion is required for conditional statements:

        char* p;

        ...

        if (p)
                ...

In this example "p" is converted to bool and then the true/false value
is checked to determine whether to execute the conditional block of
code.

Why is a bool type an advantage?  You can get a variety of opinions on
whether this is a step forward.  In C, common usage to mimic this type
would be as follows:

        typedef int Bool;

        #define FALSE 0
        #define TRUE 1

One problem with such an approach is that it's not at all type-safe.
For example, a programmer could say:

        Bool b;

        b = 37;

and the compiler wouldn't care.  Another problem is displaying values
of Boolean type:

        printf("%s", b ? "true" : "false");

which is awkward.  In C++ it is possible to set up a stream I/O output
operator specifically for a particular type, and thus output of bool
values can be distinguished from plain integral types.  This is an
example of function overloading (see next section).  Without bool as a
distinct type, usage like:

        void f(int i) {}

        void f(Bool b) {}

would be invalid.

Finally, why wasn't bool added to the language, but as a class type
found in a standard library?  This question is hard to answer, but one
possible reason is that many C implementations have supplied a Boolean
pseudo-type using a typedef and #define scheme as illustrated above,
and these implementations rely on representing Booleans as integral
types rather than as class types.


USING C++ AS A BETTER C PART 5 - FUNCTION OVERLOADING

Suppose that you are writing some software to manipulate calendar
dates, and you wish to allow a user of the software to specify dates
in one of two forms:

        8, 4, 1964 (as a triple of numbers)

        August 4, 1964 (as a string)

In C, if there is a function to convert a raw date into an internal
form (for example, the number of days since January 1, 1800), it might
look like:

        long str_to_date(int m, int d, int y) { ... }

        long str_to_date(char* d) { ... }

with one function for each of the two types of dates.  Unfortunately,
this usage is illegal in C, because two different functions cannot
have the same name "str_to_date".

In C++ this usage is legal and goes by the term "function
overloading".  That is, two or more functions may have the same name,
so long as the parameter types are sufficiently different enough to
distinguish which function is intended.  A function may not be
overloaded on the basis of its return type.

The question of what makes two function parameter lists sufficiently
different is an interesting one.  For example, this usage is not valid:

        void f(int) {}

        void f(const int) {}

whereas saying:

        void f(int) {}

        void f(long) {}

is fine.

A common place where function overloading is seen is in constructors
for a class.  For example, we might have:

        class Date {
                ...
        public:
                Date(int m, int d, int y);
                Date(char*);
        };

to represent a calendar date.  Two constructors, representing the two
ways of creating a date object (from a triple of numbers and from a
string) are specified.

What can go wrong with function overloading?  Consider an example of a
String class:

        class String {
                ...
        public:
                String();
                String(char*);
                String(char);
        };

Here we have three constructors, the first to create a null String and
the second to create a String from a char*.  The third constructor
creates a String from an individual character, so that for example 'x'
turns into a String "x".

What happens if you declare a String object like this:

        String s(37);

Clearly, the first String constructor won't be called, because it
takes no arguments.  And 37 isn't a valid char*, so the second
constructor won't be used.  That leaves String(char), but 37 is an int
and not a char.  The third constructor will indeed be called, after 37
is demoted from an int to a char.

In this case, the user "got away" with doing things this way, though
it's not clear what was intended.  Usage like:

        String s(12345);

is even more problematic, because 12345 cannot be converted to a char
in any meaningful way.

The process of determining which function should be called is known as
"argument matching", and it's one of the most difficult aspects of C++
to understand.  Function overloading is powerful, but it's smart to
use it in a way that makes clear which function will be called when.


BOOK REVIEW - THE MYTHICAL MAN-MONTH

Some of you may have heard of the book "The Mythical Man-Month" by
Fred Brooks.  It was first published in 1975 and was updated last
year.  It is published by Addison-Wesley and costs about $25, and is
considered a classic with 250,000 copies in print.  Brooks was the
manager of the project that developed OS/360 during the early 1960s.

The subject of the book is software development and the complexities
associated with it.  In the earlier chapters, which have not been
updated since the 1975 edition, he talks about a variety of issues.
One of my favorite parts is in the first chapter, entitled "The Tar
Pit".  In the discussion in this chapter he distinguishes four stages
in the evolution of a finished software product:

        (1)  a program

        (2)  a programming system, with interfaces and system
        integration

        (3)  a programming product, with generalization, testing,
        documentation, and maintenance

        (4)  a programming systems product

A program is something you might quickly put together in a few hours
or days or weeks.  But to take the additional two steps of coming up
with a programming system or programming product is a lot of
additional work, on the order of 3X as Brooks describes it.  Each of
these steps is independent, therefore Brooks talks about a 9X ratio of
cost between a program and a programming systems product.

Of course, 9X isn't a magic figure, but it captures the huge
difference in cost between hacking out a few thousand lines of code
over the weekend and putting out a polished product to customers.

The book has been updated with significant new material.  He discusses
the promise and practicality of object-oriented programming, software
reuse, and so on.

Highly recommended.


EXAMPLE C++ CLASS - MEAN AND STANDARD DEVIATION

Here is a complete code example that shows a simple but powerful way
of doing numerical calculations.  You've probably had many occasions
where you need to find the average value of a set of numbers.  You set
up a couple of variables to accumulate the count of numbers and the
total, and then divide to get the average value.

This example shows another way of doing the same thing, without
setting up any of these variables or worrying about the details of the
calculations.  Instead, you set up a Stat class object and then feed
numbers into it.  The object has an internal state that keeps track of
all the details of what numbers have been seen.  When you're done
feeding in the numbers, you can interrogate the object to give you the
average value, the number of values seen, the standard deviation (a
statistical measure), and so on.

The same technique can be used in many diverse areas.  As an exercise,
try extending this class to also compute the smallest and largest
numbers from a set, and come up with member functions that will allow
a user to retrieve these values.

#include <stdio.h>
#include <assert.h>
#include <math.h>

class Stat {
        long cnt;               // number of values
        double sumx;            // sum of values
        double sumx2;           // sum of squares of values
public:
        Stat();                 // constructor
        void add(double);       // add a value
        long n();               // get number of values
        double sum();           // get sum of values
        double mean();          // get average
        double stdev();         // get standard deviation
};

// constructor
Stat::Stat()
{
        cnt = 0;
        sumx = 0.0;
        sumx2 = 0.0;
}

// add a value
void Stat::add(double d)
{
        cnt++;
        sumx += d;
        sumx2 += d * d;
}

// get number of values
long Stat::n()
{
        return cnt;
}

// get sum of values
double Stat::sum()
{
        assert(cnt >= 1);

        return sumx;
}

// get average value
double Stat::mean()
{
        assert(cnt >= 1);

        return sumx / double(cnt);
}

// get standard deviation
double Stat::stdev()
{
        assert(cnt >= 2);

        return sqrt((double(cnt) * sumx2 - sumx * sumx) /
            (double(cnt) * double(cnt - 1)));
}

// driver program
main()
{
        Stat st;
        int i;

        for (i = 1; i <= 10; i++)
                st.add(double(i));

        printf("n = %ld\n", st.n());
        printf("average = %.2f\n", st.mean());
        printf("standard deviation = %.2f\n", st.stdev());

        return 0;
}

-------------------------

Copyright (c) 1996 Glen McCluskey.  All Rights Reserved.

This newsletter may be further distributed provided that it is copied
in its entirety, including the newsletter number at the top and the
copyright and contact information at the bottom.

Glen McCluskey & Associates
Professional C++ Consulting
Internet: glenm@glenmccl.com
Phone: (970) 490-2462
Fax: (970) 490-2463
FTP: rmii.com /pub2/glenm/newslett (for back issues)
Web: http://www.rmii.com/~glenm
