Tuesday, March 29, 2011

Creating Your Own Basic Types C++

In C++, types are separated into two regions, basic and user-defined. Basic types are those defined by the language, which generally are modeled on types supported directly by the computer hardware. These types include integers, floating point numbers, and characters. Advanced types, such as strings, structures, and classes, fall into the user-defined region. In this technique, we examine the first region, the basic type. I save the advanced types for the next technique. How many times have you written a program that required a basic integer variable to be constrained within a given range? You end up duplicating the same code over and over throughout your application, in blocks that look like this:
Best Little Stories from the Civil War, 2E: More than 100 true storiesC Programming Language (2nd Edition)Programming in C (3rd Edition)C Programming: A Modern Approach, 2nd Edition
int value = get_a_value();
if ( value < 0 || value > 10 )
{
printf(“invalid input, try again\n”);
return false;
}
Of course, after you have shoehorned all these blocks into the code, your boss comes along and tells you that the folks in the accounting department have decided that ten is no longer the magic number — now it’s 12. So, you modify all of the code, learning something in the process — namely that you’re better off using constants in this situation than variables.

Your modifications look like this:
const int maxValue = 12;
int value = get_a_value();
if ( value < 0 || value > maxValue )
{
printf(“invalid input, try again\n”);
return false;
}

You check the code into your source-code repository and sure enough, the boss comes into your office again. The accountants have requested another change. While the maximum allowable value is still 12, zero esare not allowed in the accounting system. The smallest value you are permitted to enter is 1. Grumbling, you rewrite the code one more time (taking advantage of what you have learned in the first two experiences) to create something slightly more generic:

const int minValue = 1;
const int maxValue = 12;
int value = get_a_value();
if ( value < minValue || value > maxValue
)
{
printf(“invalid input, try again\n”);
return false;
}

Implementing the Range Class In this technique, I show you a more general way to solve this problem — by using a C++ class. The idea is to just extend the basic type of int to allow for minimum and maximum values. The problem, of course, is that I still want to be able to use other types (such as integers) for comparisons and assignments and the like. The class created in the following steps handles minimum and maximum values, and restricts input within those values.

1. In the code editor of your choice, create a new file to hold the code for the implementation of the source file. In this example, the file is named ch11.cpp, although you can use whatever you choose.
2. Type the code from Listing 11-1 into your file. Better yet, copy the code from the source file on
this book’s companion Web site.

LISTING 11-1: THE RANGE CLASS
#include
#include
#include
class IntRange
{
private:
int iMin;
int iMax;
int iValue;
virtual void SetValue( int value )
{
if ( value < GetMin() )
value = GetMin();
else
if ( value > GetMax() )
value = GetMax();
iValue = value;
}
public:
IntRange(void)
{
iMin = 0;
iMax = INT_MAX;
iValue = iMin;
}
IntRange(int min, int max)
{
if ( min <= max )
{
iMin = min;
iMax = max;
}
else
{
iMin = max;
iMax = min;
}
iValue = iMin;
}
IntRange( int min, int max, int value )
{
if ( min <= max )
{
iMin = min;
iMax = max;
}
else
{
iMin = max;
iMax = min;
}
SetValue( value );
}
IntRange( const IntRange& aCopy )
{

iMin = aCopy.iMin;
iMax = aCopy.iMax;
iValue = aCopy.iValue;
}
virtual ~IntRange()
{}
virtual int GetMin(void)
{
return iMin;
}
virtual int GetMax(void)
{
return iMax;
}
// Define a few operators
IntRange& operator=(int value)
{
SetValue ( value );
return *this;
}
IntRange& operator=(double value)
{
SetValue( (int)value );
return *this;
}
virtual int GetValue(void) const
{
return iValue;
}};
If you examine this code, you will find that it verifies that the value of an integer variable falls
within a certain range. You can define your own minimum and maximum values for the range, and
the class will ensure that any value assigned to that variable falls inside that range. The interesting part of this class is the last part, comprised of the lines below the Define a few operators comment. This is where the power of C++’s extensibility shines. I have defined assignment operators so that our class can be used with the built-in types int and double. Obviously, I could add additional types here, including strings and the like, but this is enough for right now. With this power, you can now use the IntRange class tostore your data, sure that the value in the object will always be valid. That’s a comfort, and it means there’s no longer any reason to write code like the following:

int x = get_a_value();
if ( x < min || x > max )
do_some_error();
Instead, I can simply write
IntRange myRangeObj(min, max);
myRangeObj = val;
int x = myRangeObj.GetValue();
I don’t have to check the returned value, because the code requires that it be correct. There is
something else that I can do with this class, however, and that is to define external operators for
it. Being able to define an external operator is extremely beneficial because it allows users with
no access to the source code of the class to create new ways to use the class. This is something
absolutely unique to C++; no previous language has anything like it. Without having access to the
source code for this class, we can override basic operations (such as less-than, greater-than, or
equal-to) in our own code. The ability to add external operators makes it possible to add things the original programmer did not think of for the class operations.
 C Programming for the Absolute BeginnerAbsolute Beginner's Guide to C (2nd Edition)C All-in-One Desk Reference For DummiesExpert C Programming
3. Add the code from Listing 11-2 to your sourcecode file. This code could easily be added at
a later date, in a separate file, by a separate programme


LISTING 11-2: RANGE CLASS OPERATORS
bool operator<(const IntRange& aRange, int
aValue )
{
return aRange.GetValue() < aValue;
}
bool operator==(const IntRange& aRange, int
aValue )
{
return aRange.GetValue() == aValue;
}
 Practical C Programming, 3rd EditionC Primer Plus (5th Edition)Beginning C: From Novice to Professional (Beginning: from Novice to Professional)C Programming - A Beginner's Course
4. Save your source-code file and close the code editor.
Testing the Range Class

After you create a Range class, you should create a test driver that not only ensures that your code is correct, but also shows people how to use your code. Here I show you how to create a test driver that validates various kinds of input from the user, and illustrates how the Range class, as defined in the previous section, is intended to be used.
1. In the code editor of your choice, open the existing file to hold the code for your test program.
In this example, I named the test program ch11_1.cpp.
2. Type the code from Listing 11-3 into your file. Better yet, copy the code from the source file in the ch11 directory of this book’s companion Web site

LISTING 11-2: THE RANGE CLASS TEST DRIVER
int main(int argc, char **argv)
{
IntRange i20(0,20);
for (int i=1; i
{
i20 = atoi(argv[i]);
printf(“Setting value to %s, value
is now %d\n”, argv[i],
i20.GetValue() );
}
i20 = 13;
if ( i20 < 19 )
printf(“The value is under 19\n”);
else
printf(“The value is over 19\n”);
if ( i20 < 10 )
printf(“The value is under 10\n”);
else
printf(“The value is over 10\n”);
if ( i20 == 13 )
printf(“The value is 13\n”);
else
printf(“The value is NOT 13\n”);
return 0;
}
3. Compile and run the application in the operating system of your choice. If you have done everything right, you should see the following output in the shell window on your system:
$ ./a.exe 1 2 -1 30
Setting value to 1, value is now 1
Setting value to 2, value is now 2
Setting value to -1, value is now 0
Setting value to 30, value is now 20
The value is under 19
The value is over 10
The value is 13
As you can see, the Range class does not allow the values to be assigned outside of the valid
entries we defined in our source code. Notice how the Range class can be used just as if
it were a basic type that was a part of the language from the very start! This amazingly powerful
technique lets you do just about anything you want (in code, that is). It even makes possible the direct conversion of your own data types into the base type you are extending, in order to pass them directly to functions that expect the basic type.

No comments: