Re: Best practice for maintaining an internal reference/pointer to another class
On Feb 26, 4:35 am, "Sal" <a...@dotcom.com> wrote:
Alright, so I've been working on a monitoring class for a little while now
and I realized that the way I am maintaining my internal references to the
monitored class may not be the most obvious to users. Perhaps let me explain
how I am doing it now, and then I'd be welcome to suggestions to alternative
approaches. Imagine you have two classes, ClassA, and ClassB. ClassA is just
some class that changes its internal state from time to time, and ClassB is
a class that provides additional content, based on the current state of a
ClassA instance (it actually provides significant analysis that is
independent of ClassA, so it really doesn't make sense to merge the two
classes). So, ClassB essentially needs to contain an internal reference to a
ClassA object:
class ClassA;
class ClassB
{
ClassA *myItem;
public:
ClassB(const ClassA &item)
: myItem(&item) { }
}
I'm sure you see the problem with this immediately; although the intention
is for the user to "new" a ClassA and pass it into the constructor to ClassB
(that way the internal pointer of ClassB won't change), the constructor
takes in a reference. Which means theoretically the user could create a
ClassA on the stack, pass it to a ClassB, then have it deleted and now the
ClassB points to garbage.
The immediate problem that I see is the invalid use of the const
keyword. :-) However, I will stay focused on the question at hand...
Alternatively, it could be written as:
class ClassB
{
ClassA *myItem;
public:
ClassB(const ClassA *item)
: myItem(item) { }
}
But, I'm under the impression that passing pointers around probably isn't
the best practice (in general). So, I guess my question is which one makes
more sense from an outside user's standpoint (or does neither make sense)?
There isn't much chance of getting around keeping an internal pointer, and
obviously I know that it will be fragile (since whomever passed in the
ClassA to begin with has free reign to destroy the object at will), but I'm
looking for the best practice so that the consumer of ClassB will think:
"hey, this ClassB is storing an internal reference, maybe I shouldn't delete
this ClassA".
My preferred style is to use pointers when I want to indicate that the
object is going to be referenced beyond the lifetime of the function
and references when it is not. So in this case, using a pointer in the
constructor would indicate to the programmer that the object will be
stored for later use. It would also help if the class had a member
function for unseating the pointer. So something like this:
class ClassB
{
ClassA* myItem;
public:
ClassB(ClassA* anItem) : myItem(anItem) { }
void disconnectItem() {
myItem = 0;
}
// or
void resetItem(ClassA* anItem = 0) {
myItem = anItem;
}
};
I also like Ulrich's suggestion that you explore aggregation if
ClassB's state is intimately linked to the state of the ClassA object
that it's connected to. With the code as it stands, someone could
easily change the state of a ClassB object indirectly (without using
its interface,) which is generally considered a no-no.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]