 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
manfred Guest
|
Posted: Fri Oct 24, 2003 7:12 pm Post subject: user-defined conversion instead of public derivation? |
|
|
hi all,
in our project we are using a certain class (it's an
ACE_Array<someType>) in a lot of places. The following two
requirements apply:
(A) In addition to the standard array interface we use some special
insertion and lookup 'algorithms'.
(B) we have a number of 3rd-party subsystems that operate on
ACE_Array<someType> objects which are passed by reference.
I'm trying to wrap up this code and came up with three design
alternatives, none of them very convincing:
(1) public derivation: create a new class that publicly derives from
ACE_Array<someType> and adds the special algorithms as member
functions. This is problematic since the base class has a non-virtual
destructor. apart from this limitation I think it would be the right
choice, even though the base has no virtual functions at all.
(2) use free functions for the special insertion/lookup, passing the
array objects as arguments. I (and other implementers) find this
rather un-intuitive, since insertion and lookup are operations acting
on arrays and 'member' functions would seem 'natural' here.
(3) use aggregation: create a new class that aggregates an
ACE_Array<someType>; then write simple forwarders for all (or most)
array functions, plus the additional insertion and lookup methods:
class myArrayClass {
public:
// duplicate needed array functions here and forward
// add special insertion and lookup methods
private:
ACE_Array<someType> theArray;
};
I'm currently thinking about option (3) which seems safe; however, I
cannot pass such a class to a function that expects an
ACE_Array<someType>. My question now is: would it be reasonable to add
a user-defined conversion
operator ACE_Array<someType>& () { return theArray; } // good?
that returns a reference to the aggregated member? Surely this would
give up encapsulation of the member variable, but I guess that's just
what i need here...
thanks,
-manfred
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Antonio Maiorano Guest
|
Posted: Sat Oct 25, 2003 8:23 am Post subject: Re: user-defined conversion instead of public derivation? |
|
|
Hi Manfred,
My personal advice is the following:
1) Don't subclass the array. Apart from the fact it does not have a virtual
destructor, typically you are supposed derive a class to "change" its
behavior - since there are no virtual functions, you will only be "adding"
behavior, and this to me is not a valid enough reason to go with this.
2) Writing a wrapper class is not a terrible solution, since as you said, it
is more convenient to programmers and readers of the code because you will
be calling InsertSpecial() (for example) directly on the class instance.
Adding your type-conversion will solve the problem of passing it to
functions that expect the aggregate array type; however, it does not solve
the problem of calling those methods on the aggregate type without a
typecast. Your code will look like this:
MyArrayWrapper arr(ACE_Array<int>()); // Create wrapper over ACE_Array
instance
arr.InsertSpecial(5); // Call our own special insertion method (nice and
convenient)
static_cast<ACE_Array&>(arr).Insert(6); // Call ACE_Array method, not so
convenient :(
3) In the end, go for the free functions. This is not as inconvenient as you
think. Think about the STL algorithms, for instance, which contain many free
functions that work on containers. This is a simpler and more flexible
solution, in my honest opinion.
Hope this helps you out!
Tony
"manfred" <mzinner (AT) snafu (DOT) de> wrote
| Quote: | hi all,
in our project we are using a certain class (it's an
ACE_Array<someType>) in a lot of places. The following two
requirements apply:
(A) In addition to the standard array interface we use some special
insertion and lookup 'algorithms'.
(B) we have a number of 3rd-party subsystems that operate on
ACE_Array<someType> objects which are passed by reference.
I'm trying to wrap up this code and came up with three design
alternatives, none of them very convincing:
(1) public derivation: create a new class that publicly derives from
ACE_Array<someType> and adds the special algorithms as member
functions. This is problematic since the base class has a non-virtual
destructor. apart from this limitation I think it would be the right
choice, even though the base has no virtual functions at all.
(2) use free functions for the special insertion/lookup, passing the
array objects as arguments. I (and other implementers) find this
rather un-intuitive, since insertion and lookup are operations acting
on arrays and 'member' functions would seem 'natural' here.
(3) use aggregation: create a new class that aggregates an
ACE_Array<someType>; then write simple forwarders for all (or most)
array functions, plus the additional insertion and lookup methods:
class myArrayClass {
public:
// duplicate needed array functions here and forward
// add special insertion and lookup methods
private:
ACE_Array<someType> theArray;
};
I'm currently thinking about option (3) which seems safe; however, I
cannot pass such a class to a function that expects an
ACE_Array<someType>. My question now is: would it be reasonable to add
a user-defined conversion
operator ACE_Array<someType>& () { return theArray; } // good?
that returns a reference to the aggregated member? Surely this would
give up encapsulation of the member variable, but I guess that's just
what i need here...
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Lars Tetzlaff Guest
|
Posted: Sat Oct 25, 2003 8:31 am Post subject: Re: user-defined conversion instead of public derivation? |
|
|
hi
manfred wrote:
....
| Quote: | (1) public derivation: create a new class that publicly derives from
ACE_Array<someType> and adds the special algorithms as member
functions. This is problematic since the base class has a non-virtual
destructor. apart from this limitation I think it would be the right
choice, even though the base has no virtual functions at all.
|
Where is the problem?
| Quote: |
(2) use free functions for the special insertion/lookup, passing the
array objects as arguments. I (and other implementers) find this
rather un-intuitive, since insertion and lookup are operations acting
on arrays and 'member' functions would seem 'natural' here.
|
Have a look at STL: find, replace, merge are funtions operating on
containers. If you do not need access to private members: why not?
Maybe you even can use STL algorithms?
Lars
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Aaron Bentley Guest
|
Posted: Sun Oct 26, 2003 5:06 am Post subject: Re: user-defined conversion instead of public derivation? |
|
|
Lars Tetzlaff wrote:
| Quote: | hi
manfred wrote:
...
(1) public derivation: create a new class that publicly derives from
ACE_Array<someType> and adds the special algorithms as member
functions. This is problematic since the base class has a non-virtual
destructor. apart from this limitation I think it would be the right
choice, even though the base has no virtual functions at all.
Where is the problem?
|
Deleting a DerivedArray<T> through a pointer of type ACE_Array<T> * will
invoke ~ACE_Array<T>, but not ~DerivedArray<T>. If the derived class
has no members, that might be acceptable, but invoking the correct
destructor is usually a good idea.
Aaron
--
Aaron Bentley
www.aaronbentley.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
manfred Guest
|
Posted: Sun Oct 26, 2003 7:12 pm Post subject: Re: user-defined conversion instead of public derivation? |
|
|
On 26 Oct 2003 01:06:05 -0400, Aaron Bentley
<aaron.bentley (AT) utoronto (DOT) ca> wrote:
| Quote: | Deleting a DerivedArray<T> through a pointer of type ACE_Array<T> * will
invoke ~ACE_Array<T>, but not ~DerivedArray<T>. If the derived class
has no members, that might be acceptable, but invoking the correct
destructor is usually a good idea.
in fact, while most compilers will actually create such code the |
standard says that 'behaviour is undefined' in such a case.
this has been discussed several times on this list already. however,
I'm still not sure what to think of it - even the mentioned
ACE_Array<T> class derives publicly from ACE_Array_Base<T>, and the
base has a non-virtual dtor!
Even the STL uses non-virtual dtors in base classes. herb sutter
discusses this in
http://www.gotw.ca/publications/mill18.htm
and just says 'you can reasonably assume that such code (deleting
derived through a base pointer) won't exist in this case'.
So, it seems like there is a guideline rejecting derivation from a
non-virtual dtor class, but everyone is violating this guideline
anyway...
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Lars Tetzlaff Guest
|
Posted: Sun Oct 26, 2003 7:14 pm Post subject: Re: user-defined conversion instead of public derivation? |
|
|
Aaron Bentley wrote:
| Quote: | Lars Tetzlaff wrote:
hi
manfred wrote:
...
(1) public derivation: create a new class that publicly derives from
ACE_Array<someType> and adds the special algorithms as member
functions. This is problematic since the base class has a non-virtual
destructor. apart from this limitation I think it would be the right
choice, even though the base has no virtual functions at all.
Where is the problem?
Deleting a DerivedArray<T> through a pointer of type ACE_Array<T> * will
invoke ~ACE_Array<T>, but not ~DerivedArray<T>. If the derived class
has no members, that might be acceptable, but invoking the correct
destructor is usually a good idea.
Aaron
|
Thats right! But if you only use the array ( manfred: (B) we have a
number of 3rd-party subsystems that operate on ACE_Array<someType>
objects which are passed by reference ) there is no problem! You, as the
caller, know what to delete.
Lars
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Aaron Bentley Guest
|
Posted: Mon Oct 27, 2003 12:04 am Post subject: Re: user-defined conversion instead of public derivation? |
|
|
Lars Tetzlaff wrote:
| Quote: | Aaron Bentley wrote:
Lars Tetzlaff wrote:
Where is the problem?
Deleting a DerivedArray<T> through a pointer of type ACE_Array<T> * will
invoke ~ACE_Array<T>, but not ~DerivedArray<T>. If the derived class
has no members, that might be acceptable, but invoking the correct
destructor is usually a good idea.
Thats right! But if you only use the array ( manfred: (B) we have a
number of 3rd-party subsystems that operate on ACE_Array
objects which are passed by reference ) there is no problem! You, as the
caller, know what to delete.
|
In making a choice between these alternatives, you've got to weigh
advantages and disadvantages. I'm not saying "Don't do (1)". You asked
what the disadvantage of (1) is, and I replied.
Public inheritance is a defensible choice here, but has disadvantages--
you've got to be careful how such objects are deleted. You've got to be
sure that nothing in the lower-level code is deleting the references.
You've got to educate coworkers.
Assuming an intelligent programmer isn't a great solution, because even
intelligent programmers can do dumb things.
Aaron
--
Aaron Bentley
www.aaronbentley.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Aaron Bentley Guest
|
Posted: Mon Oct 27, 2003 12:05 am Post subject: Re: user-defined conversion instead of public derivation? |
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
manfred wrote:
| Quote: | On 26 Oct 2003 01:06:05 -0400, Aaron Bentley
[email]aaron.bentley (AT) utoronto (DOT) ca[/email]> wrote:
Deleting a DerivedArray<T> through a pointer of type ACE_Array<T> * will
invoke ~ACE_Array<T>, but not ~DerivedArray<T>. If the derived class
has no members, that might be acceptable, but invoking the correct
destructor is usually a good idea.
in fact, while most compilers will actually create such code the
standard says that 'behaviour is undefined' in such a case.
|
Oh, neat. And here I was thinking it would merely do the wrong thing.
| Quote: | this has been discussed several times on this list already. however,
I'm still not sure what to think of it - even the mentioned
ACE_Array<T> class derives publicly from ACE_Array_Base<T>, and the
base has a non-virtual dtor!
|
Well, the answer then is "if you delete a type derived from
ACE_Array_Base<T> by pointer, ensure the pointer type matches the object
type".
| Quote: | Even the STL uses non-virtual dtors in base classes. herb sutter
discusses this in
http://www.gotw.ca/publications/mill18.htm
and just says 'you can reasonably assume that such code (deleting
derived through a base pointer) won't exist in this case'.
So, it seems like there is a guideline rejecting derivation from a
non-virtual dtor class, but everyone is violating this guideline
anyway...
|
What's illegal is deleting classes derived from std::unary_function *by
pointer*. The STL is not violating that guideline, as far as I know.
Personally, I've only derived from an STL base once. Herb argues that
non-virtual destructors should be protected, so that those objects can't
be deleted by pointer.
In the same article, he says "Don't derive from concrete classes", and
references Scott Meyers.
Aaron
- --
Aaron Bentley
www.aaronbentley.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQE/nEfWeI1F3j5npt0RAtccAKCDNADDMRNqLtiXmG4X9oQRRdvqfwCfa/My
IOHai68BFO7coX4l26RtbgM=
=vLVc
-----END PGP SIGNATURE-----
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|