From: DeMarcus on 18 Feb 2010 08:26 Hi, I have some trouble understanding the true meaning of const. Please consider this example. class Store { public: void add( int* item ) { /* ... */ } }; class Item { public: Item( int item ) : item_(item) {} void giveToStore( Store& store ) const { store.add( &item_ ); } private: int item_; }; Now, this gives me "invalid conversion from 'const int*' to 'int*'" when exposing item_ in store.add( &item_ ). What's the way of thinking here? I have several options. 1. Remove const from giveToStore. This seems wrong since giveToStore() does not alter any internals, hence it should be const. Pretty much like boost::shared_ptr::get(). 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) ); I don't like const_cast, it immediately seems like wrong design. 3. Make i_ mutable, i.e. mutable int i_; Seems like what I'm looking for, however, great care has to be taken so we later don't add another const function that accidentally alters i_. 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu, Item 11 - Hide information. Basically it says; "Don't expose internal information from an entity that provides an abstraction.". However, my real problem (illustrated with Item) is a kind of wrapper similar to boost::shared_ptr and I need something like boost::shared_ptr::get(). Therefore I'm clueless about finding an alternative design. How would you approach such const situation? Thanks, Daniel -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Bart van Ingen Schenau on 18 Feb 2010 18:13 On Feb 19, 2:26 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote: > Hi, > I have some trouble understanding the true meaning of const. > Please consider this example. > > class Store > { > public: > void add( int* item ) { /* ... */ } > > }; > > class Item > { > public: > Item( int item ) : item_(item) {} > void giveToStore( Store& store ) const { store.add( &item_ ); } > > private: > int item_; > > }; > > Now, this gives me "invalid conversion from 'const int*' to 'int*'" when > exposing item_ in store.add( &item_ ). What's the way of thinking here? > I have several options. > > 1. Remove const from giveToStore. This seems wrong since giveToStore() > does not alter any internals, hence it should be const. Pretty much like > boost::shared_ptr::get(). How do you know that giveToStore() does not cause item_ to be changed? The function passes it as a writable pointer on to Store::add(), which might try to update the object passed to it (if not now, then possibly in a future revision). In your options, you were missing number one: 1a. Change the function Store::add() to accept a 'const int *', or provide an overload that accepts such a parameter. <snip> > How would you approach such const situation? I would either change Store::add, or I would make giveToStore non- const, or I would do a complete re-design as last resort. All the rest of your options were just hacks to appease the compiler. > > Thanks, > Daniel > Bart v Ingen Schenau -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Marco Nef on 18 Feb 2010 18:12 "DeMarcus" <use_my_alias_here(a)hotmail.com> schrieb im Newsbeitrag news:4b7d4a63$0$282$14726298(a)news.sunsite.dk... > Hi, > I have some trouble understanding the true meaning of const. > Please consider this example. > ..... > Now, this gives me "invalid conversion from 'const int*' to 'int*'" when > exposing item_ in store.add( &item_ ). What's the way of thinking here? > I have several options. > > 1. Remove const from giveToStore. This seems wrong since giveToStore() > does not alter any internals, hence it should be const. Pretty much like > boost::shared_ptr::get(). > > 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) ); > I don't like const_cast, it immediately seems like wrong design. > > 3. Make i_ mutable, i.e. mutable int i_; > Seems like what I'm looking for, however, great care has to be taken so > we later don't add another const function that accidentally alters i_. > > 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu, > Item 11 - Hide information. Basically it says; "Don't expose internal > information from an entity that provides an abstraction.". However, my > real problem (illustrated with Item) is a kind of wrapper similar to > boost::shared_ptr and I need something like boost::shared_ptr::get(). > Therefore I'm clueless about finding an alternative design. > > > How would you approach such const situation? It is correct, that the method "giveToStore" does not change its member, but it gives away the guarantee that the member won't be changed anywhere else. So it's definitely not const. I can see two possibilities: - Implement a store that does not change the items so they can be const within the store. - Take away the const of "giveToStore". - mutable and const_cast almost always identify design errors. Marco -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: peter koch larsen on 18 Feb 2010 18:13 On 19 Feb., 02:26, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote: > Hi, > I have some trouble understanding the true meaning of const. > Please consider this example. > > class Store > { > public: > void add( int* item ) { /* ... */ } > > }; > > class Item > { > public: > Item( int item ) : item_(item) {} > void giveToStore( Store& store ) const { store.add( &item_ ); } > > private: > int item_; > > }; > > Now, this gives me "invalid conversion from 'const int*' to 'int*'" when > exposing item_ in store.add( &item_ ). What's the way of thinking here? > I have several options. > > 1. Remove const from giveToStore. This seems wrong since giveToStore() > does not alter any internals, hence it should be const. Pretty much like > boost::shared_ptr::get(). > No. Looking at the declaration of Store::add, Item::GiveToStore can't be const (Store::add changes what is passed to it), so you should remove const from GiveToStore. > 2. Do a const_cast, i.e. store.add( const_cast<int*>(&i_) ); > I don't like const_cast, it immediately seems like wrong design. I agree. > > 3. Make i_ mutable, i.e. mutable int i_; > Seems like what I'm looking for, however, great care has to be taken so > we later don't add another const function that accidentally alters i_. Mutable should be used only for parts that "really don't belong to the object". Mutable objects are used to cache calculations. > > 4. Redesign according to C++ Coding Standards by Sutter & Alexandrescu, > Item 11 - Hide information. Basically it says; "Don't expose internal > information from an entity that provides an abstraction.". However, my > real problem (illustrated with Item) is a kind of wrapper similar to > boost::shared_ptr and I need something like boost::shared_ptr::get(). > Therefore I'm clueless about finding an alternative design. I don't really understand that part. > > How would you approach such const situation? As said, I would remove the const from AddToStore. It might just be possible, however, that the problem is with Store::add. Does it really need to modify its argument? If not, you should add a const and make Store::add take an int const*. /Peter -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Paul Bibbings on 18 Feb 2010 18:10 DeMarcus <use_my_alias_here(a)hotmail.com> writes: > Hi, > I have some trouble understanding the true meaning of const. > Please consider this example. > > class Store > { > public: > void add( int* item ) { /* ... */ } > }; > > class Item > { > public: > Item( int item ) : item_(item) {} > void giveToStore( Store& store ) const { store.add( &item_ ); } > > private: > int item_; > }; > > Now, this gives me "invalid conversion from 'const int*' to 'int*'" when > exposing item_ in store.add( &item_ ). What's the way of thinking here? > I have several options. <snip /> Whilst not wanting to reject out of hand the options you outine <snipped> I I have the sense that, in cases where such workarounds seem required by a given design, this is usually indicative of there being serious flaws in the design itself, which should probably be reconsidered as a whole. In the case of your design here I have a sense of ill ease arising from the issue of lifetimes. You're wanting your Store instances to maintain pointers to a data member of Items instances when those instances themselves are not managed by the Store. What happens to the viability of your store if/when its `Items' go out of scope? Though I am sure that your example here is reduced greatly from the problem you are actually working on, could it fit into your wider model to have your Store maintain the Item instances themselves? Then, if it still appears correct to not expose the data member Item::item widely, you could simply make Store a friend of Item, or some such thing. In any event, I would want to suggest that under such a model the whole const/non-const issue you are encountering would become much less troublesome, if it didn't vanish altogether. But, of course, I do not know your wider design, so some or all of this could be inappropriate/inapplicable. Regards Paul Bibbings -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 3 4 Prev: UML Survey Next: Repeat a typedef or include a header with the typedef? |