Letters to the editor may be sent via email to cujed@mfi.com, or via the postal service to Letters to the Editor, C/C++ Users Journal, 1601 W. 23rd St., Ste 200, Lawrence, KS 66046-2700.
Dear Dr. Plauger,
I am sending you the following suggestion in the hope that you can communicate it to the ANSI C++ committee. I realize they are close to freezing the language, and may already have done so by now, but still I thought it was worth a try.
A widely acknowledged shortcoming of C++ is the visibility (in header files) of private attributes and methods. When a new private method is added, files that include the header only for the public interface are needlessly recompiled. This can become a major nuisance in complex projects with many interdependent files.
I propose a simple addition to the language to fix this. It would not affect existing code. The idea is to allow private member functions to be defined in the implementation file without being declared in the class declaration. Such functions would have file scope, just like static functions commonly used in C. Unlike static functions in C, however, they would have access to all the private attributes and methods of the class to which they belong. The syntax could use the keyword static, thus:
static void MyClass:: method_with_file_scope( void ) { // function defined here }The compiler would disallow the declaration of the same function in the header file. If one more meaning of the already overloaded keyword static is objectionable, the keyword private (or some new keyword) could be used instead. Like conventional private member functions, these functions would not be accessible to a derived class. They would not be accessible to a friend class unless the friend is implemented in the same file.
In my experience, private member functions change more often than data members and other functions, especially during development, and they usually all live in the same source file. Although this simple change would not eliminate all needless recompilations, it would surely help.
Sincerely yours,
Jack Wathey
Dear P.J. Plauger,
Declaration of non-virtual private member functions or, did Bjarne nod? Having been a C programmer for many years, I was looking forward to the opportunity of doing some serious work in C++. But I soon found vexation and frustration.
I'm used to hiding the implementation for an ``object'' in C by declaring what you need to know to use it in a header file, and the rest in a private header file or in a .c source file. But it turns out that because member functions have to be declared in the header, a lot of implementation shows. I'm talking about the sort of functions you would usually declare as static. Like
for (i = 0; i < something ; i++) { dosomethingto(fred[i]) ; }where dosomethingto is a strictly local function invented on the spur of the moment. But in C++, you have to declare it in the header. If I try this, my current compiler says something like ``dosomethingto is not a member function of class C.'' This means that you have to advertise your implementation to all your users in the header file.
In the ARM, this requirement is justified to prevent people from ``hijacking'' the class, like this:
class C { private: int t; ... } void C::hijack() { t++ ; }But I think that this goes against Stroustrup's admirable attitude generally, that protection is there to prevent you inadvertently doing something you didn't mean to do, and not to stop you from doing what you want to do. If you wanted to hijack the class even more thoroughly you could write one or all of the member functions yourself. With most compiler/linker combinations, you would get your own implementation and no warning that there was another in the library. But this isn't called ``hijacking,'' it's called ``implementing a class!"
My proposition is that a declaration/definition of a member function that is not declared in the class should be accepted, it should be deemed to be private, its name should have file scope. Being private it would only be able to be called from other member functions (that takes care of the hijacking issue). One good thing about this is that it is not an addition to the language, and it doesn't break any existing correct code. Such functions don't affect the size of the members of the class, so it's feasible (as far as I can see).
Maybe this idea has already been discussed, and maybe even proposed. Maybe it's even on its way! Meanwhile, I have adopted another approach for my own implementation, which would go like this for class C:
class C_imp; // implementation of C class C { friend class C_imp; private: C_imp * cp ; public: // public functions of C ... protected: // functions derived classes can // inherit ... };So all the private data and functions of this class can be declared in my private header file <c_imp>
The constructor for C has to do a new on the cp member -- the only private member. The functions of C then provide a front for the real functions in C_imp. It also hides what possible classes I may or may not have inherited from in building my class.
I agree that this is a bit of a kludge, but I think, for a class of any size, it's pretty important to hide the implementation. I still have to stick declarations for all my tiny functions into the (local) declaration of C_imp, but I don't have to burden the customer with them. What's more, when they get a re-release of the code, they don't have to recompile, but only re-link.
I would be interested to know what you think about this proposal.
Yours,
Dan OestreicherThe scheme you outline is a technique sometimes used to provide additional hiding of implementation details. Even it can be hijacked, by someone who knows, or can guess, enough of those hidden details. ``Private'' doesn't necessarily mean ``secret.'' It is more a way to minimize accidental use of internal information about a class. I know of no proposals to add the kind of extension that both you and Mr. Wathey suggest, and I doubt they'll be forthcoming at this late stage. -- pjp
Dear Mr. Plauger,
I am working for a software company which has the majority of the products written in C. We think that we should shift to C++ where possible. We are trying to gather information about how it can be done from those who experienced the transition. What is a good way to start? Is there a formal procedure? Where can we get information about this? Any advice is appreciated. Thanks.
Mustafa Yorgancioglu
Tempe, AZA number of articles have been written in the trade press, over the past few years, describing experiences in moving from C to C++. You will find a few in back issues of CUJ. In fact, Bobby Schmidt's column, "The Learning C/C++urve," focuses especially on how to migrate code from C to C++. The basic rule is to take small steps, preserving old code in a mixed environment as much as possible. C++ works best for writing new code designed from the outset with object-oriented design principles in mind. -- pjp
Dear Mr. Plauger:
You might as well do it. Get it over with. Do us all a favor. Please go ahead and change the name of your once fine magazine to The C++ Users Journal so it accurately reflects the content within, and so I can no longer accuse you of false advertising. I for one still refuse to give up to the legions of bloated C++ programmers spawned by Mr. Gates and his like. Long live C for embedded programming...
Steadfastly resisting the hype,
Mark S. OutsonI think it's the programs that are bloated, not the programmers, and I have trouble blaming Bill Gates for C++. Still, we have been running light on "strictly C" articles in recent months. You'll be happy to know we've taken steps to acquire more C articles. Since C underlies so much of C++, a good C article can be relevant to all programmers -- it doesn't matter whether your forte is C or C++. Of course, as the next letter demonstrates, not everyone shares your perception of our content.-- pjp
Dear Mr. Plauger,
Alas, I find I must bid a fond farewell to The Journal, and it does seem fair, considering the many letters you receive extolling the virtues of good old CUJ, that I should address this to you. After all, balance is important. Right?
I, unfortunately, am one of those who've found that with each passing issue less and less of any worth (program-wise) appears in The Journal. Come to think of it, CUJ has never been long on programming information.
Lots of coding, to be sure, but except for an occasional article on how to handle this or that side-saddle piece of equipment, or how to re-work a few obscure statements in an algorithm of rare vintage and even rarer utility, the overriding gist of what's published in The Journal (its one claim to fame) has always been:
We peddle esoterica and are loudly proud of our total committment to the protection and preservation of the purity of the cryptic qualities of the work performed by ANSI C Standards Committee XYZ789.
Hey, isn't that how Gurus earn a living?
Truly,
Mark RhynerI personally earn most of my income writing code in C and C++ that people find worth licensing. But we can't please everyone with this magazine. Sorry to see you go. -- pjp
Dear Mr. Plauger,
I am a novice programmer in C. The past two months I've been trying to teach myself the language. The instrument that I've been using has been the Waite Group's beginning primer book, The New C Primer Plus. My question to you is the following: Are the articles presented in your periodical C/C++ Users Journal suitable for an individual with my skill level in C programming? Secondly, if my skills are not adequate what materials can you suggest that I investigate and acquire to raise my skill level adequately so as to take advantage of the material presented with in The C/C++ Users Journal?
Any advice or encouragement would be greatly appreciated.
Thank you for your time and attention.
David Hodge
dlhodge@netcom.comI suspect that only a small fraction of our articles will make sense to you right now, but that should change rapidly as you gain experience with C. The only way I know to learn any programming language is to practice writing code, preferably useful code. The more you write, the more you learn. Good luck. -- pjp
Hi Mr. Plauger,
A few months ago I started programming in C and Visual C++ again. I used C in some of my number crunching programs a few years ago. I am currently working on an embedded control system on the iRMX OS and multibus II arch (a real-time program).
I came across your magazine a few months ago...very interesting stuff. I purchased the May'96 and several of the '95 publications, all that I could find. I am in the process of ordering the CD.
Question: Has your magazine ever published any articles in the following areas: database and MPEG?
BTW I was going through the Q&A in one of the '95 pubs and wow...I was able to solve one of my lvalue/rvalue errors...many thanks!! Keep up the good work.
Cheers
AnandThe May 1996 issue which you purchased includes a database-intensive article, "Object Persistence with Relational Databases," by Chuck Allison. Another recent database-related article is "C Database Programming with ODBC," by Alex Ragen, in the November 1995 issue. We have yet to run an article on MPEG, but we would not rule it out as a future topic.
We're glad you found Pete Becker's Q&A column so immediately and tangibly useful. I imagine many of our readers have had the same experience. Of course, if you want to be sure you don't miss out on anything in the future, you could always suscribe by sending an e-mail to rdorders@mfi.com (hint, hint). Thanks for reading CUJ and thanks for writing. -- mb
Dear Mr. Plauger
I would like to open with a compliment on your articles in C/C++ Users Journal; they are both informative and well written.
I have been seeking a solution to a C++ problem for several weeks now and am no closer. I had thought to write to you earlier but did not wish to waste your time on a simple problem. For me it no longer seems simple.
I have been writing a database library for my own interest and exercise over the last several weeks. What interested me about this topic was the varied number and composition of fields that could be encountered at run time. After iterating through many data types I settled on an array of void pointers that I would cast with (CAST) or DYNAMIC_CAST<> at run time.
Here is a code sample of how I set it up:
void **fields; for (i=0;i<NumberOfFields;i++) switch(FieldType[i]){ case 'C': ((void) (field))[i] = new string; case 'N': ((void) (field))[i] = new int; ...The compiler does not know how to increment when cast to void. (This is similar to Smalltalk's bag class). Since I know the order and the type of each field I could enjoy the convenience of accessing them as an array. The problem is it is an array composed of hetrogeneous types.
I had also considered unions and a generic class. The union presented two problems: first, it wasted space; second, I wished to access the fields by the same name.
Another thought was a generic class that held all fields as characters. I felt this required too much conversion and I also would need a single function that returned different types depending on the type that the character sequence represented.
In short, I am looking for an array of pointers that allow me to access these elements, regarless of type, by the same name (ie. field[i].value).
I hope I have been clear here. Thank you very much for your time.
Sincerely,
Phill MoranYou're pretty close. Just define typenames for the various field types, then cast the void pointers appropriately, as in:
void **fields; for (i=0;i<NumberOfFields;i++) switch(FieldType[i]){ case 'C': *((Field_type_C *)field[i]) = new string; case 'N': *((Field_type_N *)field[i]) = new string; ...-- pjp