Departments


We Have Mail


Letters to the editor may be sent via email to cujed@cmp.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 Sir,

As a subscriber to your magazine, I was astonished to read the May C/C++ Tip #6 about “Making Classes Non-Derivable” and could not believe what was written there. But before jumping to conclusions, I ran a minimal code example in my (Borland Builder 4) compiler — guess what? My compiler does allow to derive from the class. What I had expected, of course — and not because of the compiler.

class NoDeriv
{
 protected:
  NoDeriv() {}
};

class CannotBeDerived: 
 private virtual NoDeriv
{
};

/* but derivation DOES work... */
class Test: public CannotBeDerived
{};

Now either this was an April’s fool joke (in May), or it was a test on the readers; I am rather surprised that a magazine like yours publishes this kind of stuff, and the author certainly does not deserve the CD-ROM.

Please correct me if I am wrong, otherwise my confidence in your magazine will go down quite a bit.

Alex D.


Marc,

I’ve just received the May 2001 C/C++ Users Journal, and while it’s worth reading (good to see Carlos Moreno writing for you!), I’m becoming accustomed to your C/C++ Tips being dubious.

This month’s is just terrible, as it claims to do something that can be done (making a class nonderivable in C++), but it fails to do it.

class final
{
protected:
   final() { }
};

class nonderivable : 
   private virtual final {
   // actually we can derive from this
   // class
};

class derivative: 
   nonderivable, virtual final {
   // derivative will initialize the
   // 'final' base object.
};

(I’ve checked that with Comeau’s online compiler, with a gcc 3.0 pre-release, and with my own understanding of the Standard.)

We can derive from a class that has a private virtual base, by also having that same class as a virtual base. This is well known, I would have thought, and so a technical review should have picked it up. The standard idiom is to make the class nonderivable a friend of final (called PriVirFinal in the article), which naturally opens up the discussion of a templated solution which is not legal in C++:

template <class derivedclass final
{
friend class derived; // not legal in
                      // C++ sadly
private:
   final() { }
};

class nonderivable : final<nonderivable>
{
  // ...
};

Maybe the C++ Standard will be changed to allow this in the future, but for now we’re stuck with the non-template equivalent.

Any chance of getting a correction printed, and of making sure that the C/C++ Tips are reviewed more thoroughly in future?

On a more positive note, the April Conformance Roundup was excellent; it’s good to see CUJ taking an active part in pushing vendors and users towards understanding the importance of conformance.

Regards,

James Dennett
jdennett@acm.org

Hi James,

Thanks for reporting this bug; yes, you are right — the class can be further derived from, but the solution you propose (the template solution), as you say, is not legal in C++. But, there is yet another solution to this. Under this circumstance, I have to revert back to the original solution: using friends.

In this technique, to make both CTreeKeyError and CTreeNoItemError classes (used for exceptions) not derivable, this technique uses a “lock” class, to which the class that is not to be derived from is a friend. The lock class also has a private constructor, so it cannot be instantiated on its own. The actual class to be locked derives from the locking class with the “public virtual” access controller. Since the most derived class must initialize the virtual base, only the to-be-locked class can access the private constructor of the lock class (since this class is a friend to the lock class) to initialize it. This makes sure one cannot derive from CTreeKeyError and CTreeNoItemError classes, because the derived classes cannot initialize the virtual base. This implementation will work.

Here is the lock class:

// forward decl
template <class T, 
 class Kclass CTreeKeyError; 

template <class T, class K>
class CTreeKeyErrorLock
{
 friend CTreeKeyError<T, K>;

private:
 CTreeKeyErrorLock() {}
};

And here’s the class to be locked:

template <class T, class K>
class CTreeKeyError : 
 public virtual CTreeKeyErrorLock <T, K>
{
public:
 CTreeKeyError(const T& t, const K& k) :
  m_Data(t), m_Key(k), m_strMsg
   ("Key already exists in binary tree.") {}
 void print() const
 {
  std::cout << "Data item could not be
                added to binary tree!" 
            << std::endl;
  std::cout << "Reason: " 
            << m_strMsg 
            << std::endl;
  std::cout << "Key: " 
            << m_Key 
            << std::endl;
  std::cout << "Data: " 
            << m_Data 
            << std::endl;
 }

private:
 const T m_Data;
 const K m_Key;
 const std::string m_strMsg;
};

Hope this clarifies things; thanks for your feedback.

Cheers,

Shanker Chandrabose


As a former C++ Report subscriber (and also a current, long-time CUJ subscriber), I just wanted to let you know how much I enjoy reading (and re-reading) the “C++ Experts” columns now on <www.cuj.com>. Please, please, please do whatever it takes to keep them coming! And please let the columnists know that their efforts are greatly appreciated indeed!

Igor Firkusny

We are honored to host the C++ Experts on <www.cuj.com>. Glad you like them. We do too! We’re confident that the C++ community will benefit from their wit and wisdom for a long time to come. — cda


I just browsed through the C++ Reading List and noticed that one of the best introductory books on C++ is missing: Accelerated C++ by Andrew Koenig and Barbara E. Moo.

Maybe some of the older material can be thrown out. Now that the language and the library is standardized, it makes more sense to read books that cover Standard C++. A few older gems are still worth keeping, however, such as Coplien’s Advanced C++ or Lakos’ Large Scale C++ Software Design.

Just my $0.02.

Stefan Heinzmann

Yes, it’s definitely time to update the Reading List. It’s been outside of my job description lately, but now that the Senior Editor position has come my way, I plan on revamping it. And Andy and Barbara’s book is one of a kind, to be sure (see Francis Glassborow’s review of Accelerated C++ in the June 2001 issue of CUJ). Thanks for writing (and for reading!). — cda


I like very much your editorial for the May 2001 issue and would have liked to mail a copy to a few of my fellow professors, but I could not find it on <www.cuj.com>. It would be nice if you could also leave the editorials on the website, it would save me doing a few photocopies.

That editorial was pretty good; too bad that it is mostly the ones that agree with the content that are going to read it.

François Gros d’Aillon
fg@arabica.info.uqam.ca

The Editor’s Forums are available online beginning with the January 1998 issue. Just go to the bottom of the page for whatever issue you’re viewing for the link. — cda


Hello,

You might have received this before. The C/C++ Tip #5, p. 41 from the CUJ January 2001 edition (a C/C++ comment macro) doesn’t work with GCC, because this compiler parses out comments before macros are considered.

In general this tip is not ANSI C or ANSI C++, because the resulting comment macro is not a lexical unit of C. The Standard says that such concatenations are “undefined.”

I don’t have a neat ANSI C replacement for Mark Timperley’s solution, sorry, someone else might?

Cheers

Hugues Talbot