Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

We Have Mail


August 2001/We Have Mail


Letters to the editor may be sent via email to [email protected], 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
[email protected]

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
[email protected]

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


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.