home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!brunix!brunix!sdm
- From: sdm@cs.brown.edu (Scott Meyers)
- Subject: Re: Preventing inheritance
- Message-ID: <1993Jan11.154735.17187@cs.brown.edu>
- Sender: news@cs.brown.edu
- Organization: Brown University Department of Computer Science
- References: <1iqtnpINN283@news.cerf.net>
- Date: Mon, 11 Jan 1993 15:47:35 GMT
- Lines: 83
-
- In article <1iqtnpINN283@news.cerf.net> hlf@nic.cerf.net (Howard Ferguson) writes:
- |
- | If I create a class which I am supplying to other users, how do I
- | make sure that they do not inherit from it ever. I could overload new
- | and check the size of the object that is being allocated, but there
- | are two catchs. The first minor one is that this is a run-time check,
- | and it would be far preferable to catch this sort of thing at compile
- | time. More seriously, they could over-ride the new operator and by-pass
- | the check.
-
- More seriously still, not all objects are allocated on the heap, so new
- isn't always called.
-
- The solution to your problem sort of depends on whether you want to prevent
- actual derivation or "moral" derivation. If you only want to prevent
- actual derivation, make everything in the class private and then create a
- second class which is a friend to the first one:
-
- class StandAlone { // nobody should derive from this class
- private:
- int x, y, z;
-
- StandAlone();
- ~StandAlone();
- void foo();
- int bar() const;
-
- friend class UseMe; // this is the class clients actually use
- };
-
- UseMe contains an instance of StandAlone, and calls to functions in UseMe
- are just forwarded to this object:
-
- class UseMe {
- private:
- StandAlone s;
-
- public:
- UseMe() {}
- ~UseMe() {}
- void foo() { s.foo(); }
- int bar() const { return s.bar(); }
- };
-
- You get extra style points for nesting StandAlone inside UseMe. If you do,
- not that StandAlone's members still need to be private, otherwise friends
- of UseMe would have access to StandAlone.
-
- There are two problems with this approach. First, it's not utterly
- iron-clad, because UseMe can still derive from StandAlone, like this:
-
- class UseMe {
- class Nested: public StandAlone { ... };
- };
-
- Second, it doesn't prevent "moral" derivation: clients can still use UseMe
- as a base class, and you may not want that.
-
- A different -- substantially less direct -- approach to the problem is to
- just declare Standalone in the usual manner, but without any virtual
- functions:
-
- class StandAlone { // nobody should derive from this class
- private:
- int x, y, z;
-
- public:
- StandAlone();
- ~StandAlone();
- void foo();
- int bar() const;
- };
-
- Because none of the functions is declare virtual -- notably the destructor
- -- you might hope that clients catch on that this class is not designed for
- use as a base class. Unfortunately, that's the only thing you've got going
- for you in this case: hope.
-
- Scott
-
-
- -------------------------------------------------------------------------------
- What do you say to a convicted felon in Providence? "Hello, Mr. Mayor."
-