From: marcin.sfider on 18 Feb 2010 18:11 On 19 Lut, 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(). > boost::shared_ptr::get() returns pointer to an object that is not it's member. This way the object can be modified and the pointer cannot. In your example you pass a pointer to member of class Item. Store::add can use that pointer to modify the member, thats why the error apears. > 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? > Your example is rather odd, why does Store need to store pointers to internal data of an Item? If store needs to modify Item's internals then remove const from Item::giveToStore because calling it will lead to item_ modification (right away or in future). Else pass const int* to Store::add method. > Thanks, > Daniel Cheers Sfider -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: restor on 18 Feb 2010 18:11 > 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? Hi, There is a good practise in C++ that if the function doesn't alter its argument, it should say so explicitly using 'const': void fun( const int & ); or void fun( const int * ); or, even better (but not always possible) void fun( int ); // this is far more safe, correct, easy to read The same applies to your Item::giveToStore, if we treat it as a "non- member" function with additional *this argument: void giveToStore( const Item *, Store& ); You know that already, as you listed it in Item 1 in your list. However, the same good practise applies to function Store::add(). If it doesn't modify its argument (either immediately, or later when it is obtained from Store in other parts of your code) it should be declared: void Store::add( const int* item ); Then, you would have no error. If, however, function Store::add() does modify the int (directly or not; immediately or later), this means that function Item::giveToStore also indirectly modifies the int and it must not be declared const. There is another possibility though: 1. function Store::add() does not modify the int; 2. You are the author of class Item, and class Store is from some library that you cannot control, but still you have to use it. In this case I would go for store.add( const_cast<int*>(&i_) ). It indicates a wrong design, but not yours - that of the author of class Store. If there is anything wrong with class Item, then it is the decision to use class Store with wrong design. Regards, &rzej -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Nevin :-] Liber on 18 Feb 2010 18:10 In article <4b7d4a63$0$282$14726298(a)news.sunsite.dk>, DeMarcus <use_my_alias_here(a)hotmail.com> wrote: > 1. Remove const from giveToStore. This seems wrong since giveToStore() > does not alter any internals, hence it should be const. But it is exposing Item::item for modification, so it should not be a const member function. This is consistent with the type system. This is what I would do, if I had to expose access to an internal variable. > Pretty much like > boost::shared_ptr::get(). shared_ptr::get() does not provide a way to modify the internals of shared_ptr, so it is const. That is the difference. -- Nevin ":-)" Liber <mailto:nevin(a)eviloverlord.com> 773 961-1620 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Andrew Wall on 18 Feb 2010 18:12 "DeMarcus" <use_my_alias_here(a)hotmail.com> wrote in message news:4b7d4a63$0$282$14726298(a)news.sunsite.dk... > 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 What about the option of changing Store? class Store { public: void add(const int* item ) { /* ... */ } }; Your Store class should not be wanting to change stuff its storing away. Andrew -- [ 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! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: UML Survey Next: Repeat a typedef or include a header with the typedef? |