Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sealed (final) classes in C++

2 views
Skip to first unread message

Michal Kowalski

unread,
Jan 3, 2007, 9:26:22 AM1/3/07
to
Hello,

I have a question (and a proposal) regarding "sealing" a class.

I read FAQ
(http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.11)
and I familiarized myself with Bjarne Stroustrup's example
(http://www.research.att.com/~bs/bs_faq2.html#no-derivation)

While I'm not a great proponent of this feature barring any form of
derivation from a given class, be it public or private, I'd still consider
it
useful in some scenarios. Thus I was wondering if turning above example
written by Bjarne into template would be a good idea. With it I should
be able to say:

class myClass : sealed_class<myClass>
{
...
};

(or final_class, or whatever you prefer). Attempt to define classes
that derive from myClass shall not compile (that is constructor definition
will not compile; if only default constructor is present instantiation of
derived class won't compile).

sealed_class template would be needed to hide details (virtual derivation
from a lock class). I suppose it could be written like this:


template<class T> class sealed_class;

namespace detail {

template<class Base>
class class_locker
{
friend Base;
friend sealed_class<Base>;
class_locker() {}
class_locker(const class_locker&) {}
};

}

template<class Base>
class sealed_class : public virtual detail::class_locker<Base>
{
friend Base;
sealed_class() {}
sealed_class(const sealed_class&) {}
};


My question to you is: is this approach sound? Does
it make sense? Any obvious flaws?

One deficiency is that it doesn't actually prevent declaration
of derived class, but definition of it's constructors.

If this template was working as expected my hope is it would perhaps
pacify impatient ones that request a new C++ keyword...

Other than that I'd like to sparingly use it as a hint to fellow
programmers maintaining a source code.

Thank you,
MK


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Hyman Rosen

unread,
Jan 3, 2007, 2:35:32 PM1/3/07
to
Michal Kowalski wrote:
> template<class Base>
> class class_locker
> {
> friend Base;
> };
> My question to you is: is this approach sound? Does
> it make sense? Any obvious flaws?

The (not-so?-) obvious flaw is that the friend declaration
is illegal.

Paweł

unread,
Jan 3, 2007, 2:32:10 PM1/3/07
to
Michal Kowalski napisał(a):

> (...) Thus I was wondering if turning above example written by Bjarne


> into template would be a good idea.

> friend sealed_class<Base>;

friend class T is ill-formed.

more info at:
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1520.pdf

Greg Herlihy

unread,
Jan 4, 2007, 3:58:57 PM1/4/07
to
Hyman Rosen wrote:
> Michal Kowalski wrote:
> > template<class Base>
> > class class_locker
> > {
> > friend Base;
> > };
> > My question to you is: is this approach sound? Does
> > it make sense? Any obvious flaws?
>
> The (not-so?-) obvious flaw is that the friend declaration
> is illegal.

The friend declaration used to be illegal, but no longer. For example,
here's an eerily similar class declaration that appears in the latest
draft of the C++ Standard [§11.4/3]:

template <typename T>
class R
{
friend T;
};

Greg

Gennaro Prota

unread,
Jan 5, 2007, 4:20:11 PM1/5/07
to
On 4 Jan 2007 15:58:57 -0500, Greg Herlihy wrote:

>Hyman Rosen wrote:
>> Michal Kowalski wrote:
>> > template<class Base>
>> > class class_locker
>> > {
>> > friend Base;
>> > };
>> > My question to you is: is this approach sound? Does
>> > it make sense? Any obvious flaws?
>>
>> The (not-so?-) obvious flaw is that the friend declaration
>> is illegal.
>
>The friend declaration used to be illegal, but no longer.

It's still illegal, though very likely to be made legal for C++09. For
now an alternative is the not-so-obvious:

class final
{
protected:
final();
};

#define FINAL_CLASS private virtual final

// usage:
class my_class : FINAL_CLASS
{};

That's one approach that I believed to be not valid by reading the
standard, but one of the core working group members assured me that
the wording is unfortunate and the intent is for it to work.

___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)

Michal Kowalski

unread,
Jan 5, 2007, 9:49:04 PM1/5/07
to
{ for solutions specific for VC++ consider posting to their
dedicated newsgroup[s]. -mod }

I tried using proper syntax, that is friend class Base; before.

The snug is that neither MS VC 7.1 nor VC 8.0 grant me access to the
class internals when I do that. However illegal friend Base; works!

Am I missing something obvious?

MK

"Paweł" <ro...@atlantis.news.tpi.pl> wrote in message
news:enghlo$ri6$1...@atlantis.news.tpi.pl...

Greg Herlihy

unread,
Jan 8, 2007, 2:57:05 AM1/8/07
to
Gennaro Prota wrote:
> On 4 Jan 2007 15:58:57 -0500, Greg Herlihy wrote:
>
> >Hyman Rosen wrote:
> >> Michal Kowalski wrote:
> >> > template<class Base>
> >> > class class_locker
> >> > {
> >> > friend Base;
> >> > };
> >> > My question to you is: is this approach sound? Does
> >> > it make sense? Any obvious flaws?
> >>
> >> The (not-so?-) obvious flaw is that the friend declaration
> >> is illegal.
> >
> >The friend declaration used to be illegal, but no longer.
>
> It's still illegal, though very likely to be made legal for C++09.

Let's be clear on this point: yes, a "friend T;" declaration is "still"
illegal according to the C++98 Standard; just as it was illegal nine
years ago, and just as it will be illegal 3,852 years from now
according to the same Standard. A ratified Standard is immutable.

A post that responds to the original question by merely observing that
the friend declaration was illegal in the past - provides neither an
informative nor adequate answer. After all, completely accurate but
incomplete information can be just as misleading as completely
inaccurate information. In this case, the information is accurate but
incomplete - it leaves the reader with the impression that the friend
declaration remains illegal in C++ today - and such a conclusion is
mistaken.

If the "friend T;" declaration were still illegal today, then the
following assertions would also have to be true:

* A C++ compiler has to reject "friend T;" as a meaningless syntax
error

* the Microsoft C++ compiler accepts "friend T;" due to a defect
(or a propriety extension or [insert explanation based on your own pet
theory here]) that is present in that compiler

* The C++ Standards Committee's October 2005 vote (with one member
abstaining, none opposing) to adopt language proposal N1791 (Extended
Friend Declarations) and to revise the working paper accordingly -
never happened

All three claims are false, but letting the second one stand
uncorrected strikes me as reprehensible.

C++ compiler makers do the right thing - both by their customers and by
the Standards process itself - whenever they integrate an adopted C++09
feature into their current products in a timely fashion. Not only do
C++ programs benefit from being able to to take advantage of the new
feature, but the specification of the feature in the next C++ Standard
will be able to reflect knowledge that can be acquired only from the
experience of working with an actual implementation.

Greg

Gennaro Prota

unread,
Jan 8, 2007, 12:10:44 PM1/8/07
to
On 8 Jan 2007 02:57:05 -0500, Greg Herlihy wrote:

>Gennaro Prota wrote:
>> On 4 Jan 2007 15:58:57 -0500, Greg Herlihy wrote:
>>
>> >Hyman Rosen wrote:
>> >> Michal Kowalski wrote:
>> >> > template<class Base>
>> >> > class class_locker
>> >> > {
>> >> > friend Base;
>> >> > };
>> >> > My question to you is: is this approach sound? Does
>> >> > it make sense? Any obvious flaws?
>> >>
>> >> The (not-so?-) obvious flaw is that the friend declaration
>> >> is illegal.
>> >
>> >The friend declaration used to be illegal, but no longer.
>>
>> It's still illegal, though very likely to be made legal for C++09.
>
>Let's be clear on this point: yes, a "friend T;" declaration is "still"
>illegal according to the C++98 Standard; just as it was illegal nine
>years ago, and just as it will be illegal 3,852 years from now
>according to the same Standard. A ratified Standard is immutable.
>
>A post that responds to the original question by merely observing that
>the friend declaration was illegal in the past - provides neither an
>informative nor adequate answer.

Are you in a bad day? What I was saying is that in *current* C++
(which means 'the language specified in the 2003 standard') the
declaration is illegal. Full stop (sorry but given your tone I didn't
even read the rest of your post).

___

\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)

--

James Kanze

unread,
Jan 8, 2007, 12:53:22 PM1/8/07
to
Greg Herlihy wrote:

[...]


> C++ compiler makers do the right thing - both by their customers and by
> the Standards process itself - whenever they integrate an adopted C++09
> feature into their current products in a timely fashion. Not only do
> C++ programs benefit from being able to to take advantage of the new
> feature, but the specification of the feature in the next C++ Standard
> will be able to reflect knowledge that can be acquired only from the
> experience of working with an actual implementation.

That's actually debatable. A lot depends on just how stable the
feature is, and what the probability is that it will still
change before the final standard. And the target set of users
for the compiler; activating certain new features with special
options is fine for a compiler targetting users who actually
read the documentation, and realize that they're using an
experimental and unstable feature, and that they may have to
change their code later, when the final standard is adopted.
It's definitly not a good idea for the default behavior of a
compiler used by a lot of naive programmers.

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34

ta0...@yahoo.com

unread,
Jan 9, 2007, 8:00:03 AM1/9/07
to

Gennaro Prota wrote:
> On 4 Jan 2007 15:58:57 -0500, Greg Herlihy wrote:

...

> class final
> {
> protected:
> final();
> };
>
> #define FINAL_CLASS private virtual final
>
> // usage:
> class my_class : FINAL_CLASS
> {};

I think this is the cleanest solution I've seen, but (answering to all)
I don't think that potentially changing the structure of the binary
output for something that essentially has nill run-time functionality
should ever be considered clean. Why not just add the word "final" to
the standard? That doesn't add any overhead to the program, at compile
time or at run time. Or just use private constructors and factories,
design classes to be safe as base classes, etc. I can understand Java
protecting programmers from themselves, but I don't see any need for
that in C++.
ta0kira

Gennaro Prota

unread,
Jan 11, 2007, 10:12:33 AM1/11/07
to
On 9 Jan 2007 08:00:03 -0500, ta0...@yahoo.com wrote:

>Gennaro Prota wrote:
>> On 4 Jan 2007 15:58:57 -0500, Greg Herlihy wrote:
>
>...
>
>> class final
>> {
>> protected:
>> final();
>> };
>>
>> #define FINAL_CLASS private virtual final
>>
>> // usage:
>> class my_class : FINAL_CLASS
>> {};
>
>I think this is the cleanest solution I've seen, but (answering to all)
>I don't think that potentially changing the structure of the binary
>output for something that essentially has nill run-time functionality
>should ever be considered clean.

Yeah, I consider both the original trick and the variation above mere
curiosities. In practice, I've never felt a need to make a class final
in C++ (not that it can really be done: neither of the variations
prevent derivation in itself or usage of (accessible) static members).

___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)

--

0 new messages