Prev: exact difference between C style and static_cast, const_cast
Next: Best practice for maintaining an internal reference/pointer to another class
From: Sal on 25 Feb 2010 16:35 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. 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". - Sal -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 26 Feb 2010 05:32
On 26.02.2010 10:35, Sal 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.(....) > 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 Don't EVER use const-references for this. See a recent thread started by me: http://compgroups.net/comp.lang.c++.moderated/Why-you-should-never-use-a-const-parameter-to-initialize-a-const-member > ClassB points to garbage. 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)? Well, using a pointer to track an external entity makes absolute sense in C++ to me so I think this solution is quite OK. > 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". > While a shared_ptr or weak_ptr may be a good tool here, it may also be that it's overkill (not performance or something - just the complexity of introducing the smart ptr type) If you have to construct ClassB with a ClassA object, for me it's absolutely OK to have a comment/requirement stating that ClassB will track ClassA and any operation involving ClassB is only defined if ClassA isn't destroyed. I find that this is often sufficient. br, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |