By Reg. Charney
Recently, I was using a powerful non-C++ class library. Within it guts, it had an important class that kept a container of items that I needed to extend. However, the design of the class precluded my doing this from outside the class itself. This meant that I had two basic choices: take ownership of the class forever; or foregoing changing the original class and designing a complete replacement. Neither choice was a very appetizing. In fact, if the original class had been properly designed, I would not have faced this decision at all and could have extended the class easily.
I would like to talk about avoiding this problem in future. But first, we need to discuss a few general principles. When we ask a container to hold information for us, we expect it to do that, regardless of what we do with the original copy of the data. For example, if a container is meant to hold a set of book titles, then it is safest for all concerned if it keeps copies of the titles. In that way, we can do anything we need to do with the original data and know our collection is safe as would happen if the book titles are read off a database, one title per record/row at a time. A second general principle states it is often better to keep pointers to data in a collection than to keep the data itself. The main reason is to allow for polymorphism. We will discuss that a little later. However, it is tempting to pass the pointers that you generate to your data to the collection and let it keep those copies. Great care must be exercised when doing this. Since you generate the pointers, you have nominal ownership of the data being pointed at. Thus, you have the ability to delete the data whenever you wish, even though the data is still being referenced by elements of the collection. This often causes very ugly problems at program termination.
| I use some coding
conventions when I am writing code in limited space like
this column:
I use the using namespace std; statement. However, it is almost always better to use explicitly qualified instances of std members. For example: list<X> lx; and would be better written as: std::list<X> lx; and I have also in-lined all the member functions. Their declarations and definitions should be in different source files. |
In this simple example, class A has a container of class X objects. We can add items to the container in A and to print the contents of the container that A holds. Since A will be extended, some of its member functions are virtual. Class Y is derived from X. Also, I wanted to be able to add both stack and heap variables to the collection.
(For simplicity in this column, I have used an STL std::list container. While I am working from the assumption that templates are not available, as is the case in other languages like Java and Delphi, I have used the one instance of a list of X objects. Other languages have containers that can hold references to generic objects).
| #include
<iostream> #include <string> #include <list> using namespace std; class X { class Y : public X { class A { struct B : public A { int main() |
The add() function must be overridden (as in //2) , else derived classes will be truncated at //1 when the copy constructor is called prior to the pointer being inserted into the collection.
The exact route by which things have become part of C or C++ is often shrouded in private interactions. Throughout much of the development of ISO Standard C and pre-standard versions of C++ Brian Kernighan and Bjarne Stroustrup were separated by a few feet of corridor. That means that ideas were certainly being swapped back and forth as both language designers have a high regard for each other.
The public position has always been that const was an invention by Bjarne Stroustrup and that volatile was the invention of some member of J16. There were several motivations for introducing const into C++, probably the biggest was to couple it with references to allow passing of arguments that would behave much like value arguments whilst having the efficiency of a pass by pointer.
Once the decision had been made to provide const reference parameters, the grammar of the language almost inevitably led to other uses of const. But the point to note is that in order to support the semantics of const references C++ also needed to require const correctness. By that I mean that use of an object via a const guaranteeing name must honour that promise.
const correctness has a hidden cost in that a return value based on a const qualified object must retain that qualification. The consequence is that objects can acquire const protection in their passage through a function. One of the classic examples is found in the Standard C Library; strstr(). This function takes a pointer to a const array of char and returns a pointer to an array of char in C. That will not do in C++ because the return value is based on the pointer provided as an argument. The function promises to prevent the data pointed to from being changed, but the return does not support that promise.
C++ has a simple fix for that problem; it uses a pair of overloaded functions. One function takes and returns a char const * and the other takes and returns a char *. There is also a basic C++ programming idiom that effectively allows the same source code to define both functions:
| char const*
strstr(char const*,char const*); inline char* strstr(char* s1,char const* s2) { return const_cast<char *>(strstr(const_cast<char const *> s1, s2)); } |
which effectively instructs the compiler to use the implementation of the const version for the non-const one if the first argument is not const. but return a plain char*.
The point I am making here is that C++ const correctness relies on function overloading in order to work. It is not immediately obvious to the casual observer that const correctness has anything to do with function overloading.
Remove function overloading and you are faced with a very different set of circumstances which C programmers call const poisoning.
Even implementing such potentially helpful concepts such as const comes at a cost. Next time you find yourself asking for some new feature to be added in the next revision of your favourite language, stop and ask yourself what hidden costs there may be. I happen to think that C would benefit for a controlled form of function overloading, but that is another story that I will leave for next month.
By Reg. Charney
Tax season is rapidly approaching. Paying taxes often involves a complex series of forms and rules that are beyond any single person’s ability to comprehend and fill out correctly. That is why many Americans need to pay an additional tax in the form of purchasing tax software or tax advice. (Think of the savings if the tax system was simpler and more equitable.)
We now have an additional quirk in dealing with our taxes. As reported by Walter Mossberg in the Wall Street Journal on January 30, 2003, we also have spyware to contend with when we try to use the latest version of TurboTax from Intuit.
It seems that Intuit now treats all its customers like criminals. Intuit believes that you are intent on stealing their software by handing out copies of the software to other members of your family. To prevent this criminal behavior, Intuit secretly installs a spyware program from Macrovision called SafeCast. It supposedly ensures that TurboTax is only running on the one PC on which the mandatory “activation” occurred. You activate your copy of TurboTax when you register it online. This process then secretly installs the spyware program and you are exposed. By the way, this spyware program is not uninstalled when you remove TurboTax, nor does it cease operating when tax season is over. To defend the indefensible, Intuit has since claimed that no personal information, like income and expenses, are sent anywhere—only program usage is monitored. Yea, we should believe a company that treats us like criminals and spies on us in secret. All this while handling our most confidential information.
I agree with Walter Mossberg—get the excellent competing product TaxCut by H&R Block. It is less expensive and it does not spy on you. Also your whole household is licensed to use it.
I was contact early this month by Luby Aczel, a Volunteer Coordinator for the non-profit Northern California studio of Recording for the Blind and Dyslexic. They create and lend educational material on CD or four track cassette to individuals with learning or visual disabilities. They need volunteers to read the many technical and computer manuals for which they get requests. Please visit their web site at www.rfbd.org to find out more about them. You can also contact Luby Aczel, at 650-493-3717, ext. 13
Extreme Programming Perspectives by Michele Marchesi, Giancarlo Succi, Don Wells, and Laurie Williams, Addison-Wesley, 2002, ISBN 0-201-770055-9
Rating: Highly Recommended
Reading Level: Easy.
This book is a comprehensive collection of articles by many authors on various aspects of Extreme Programming.
No specific experience in any one programming language or environment. It is assumed that the reader has significant programming and architecture experience.
The style is very readable from all authors. This speaks well of the authors, editors, and XP in general. Bear in mind that XP considers clear communication and expression an essential component of a successful project.
I do not have years of XP experience. I think, in general, that it is difficult to define precisely the XP "domain". The book presents a wealth of perspectives by people who understand and convey the topic well. I am pleased by the coverage.
I found no errors worth mentioning. The content of the book was not so technical that errors in a sample algorithm would be an issue.
Extreme Programming is an approach that I think has much merit. Its adoption, however, encounters resistance due to misconceptions about what it is and the zealous behavior of its practitioners. This book serves both the potential adopter and the practitioner by viewing XP from many angles and answering tough questions.
— Al Bauer
By Reg Charney and Ali Çehreli
I have included two figures in this month’s column. I was stuck by the similarities of seemingly independent IT areas: job openings by type of computer language; and job openings by type of platform. In both cases and across most series, there seems to be a flattening out and even a slight increase in job openings. Also, this has gone on for more than three months. I also have antidotal evidence that things may be turning around. I and some of my acquaintances have been approached about job openings without explicit effort on our part.

