Dealing with const

A

Alex

Hi. I'll try my problem with this example:

class C {
protected:
virtual int* getProtected(int index)=0;
public:
const int* get(int index) const
{ return (const int*) getProtected(index); }

virtual void set(int index, int value)
{ *getProtected(index) = value; }
...
};

class D : public C {
protected:
int* getProtected(int index) { ... }
};


I need a way to set a value and get a const pointer to that thing. I
want the base class to provide a standard way for set, which is just
copy the value. My approach is to make it easy: the child classes only
would need to implement getProtected and get() and set() will work ok.
If that class needs to do some extra processing when set() is called,
it can implement it, but otherwise it will work ok. getProtected is
protected to prevent to get a non-const pointer outside the class.

I don't know if you can understand me. Anyway, my problem is that that
doesn't work, because getProtected is a const member function and get()
is const.

Can you help me?

Thanks!!
 
L

Luke Meyers

One thing first -- there is an important difference between a "const
pointer" (T * const) and a "pointer to constant" (const T *, T const
*). It's a bit confusing to refer to the latter as the former. The
linguistic awkwardness of the latter is probably the lesser evil.

Anyway, on to your question... your problem arises from an incongruous
policy with regard to state modification. A const member function
promises not to modify the host object's state, either directly
(assigning to a member variable) or indirectly (calling a non-const
member function). If it is your policy to allow getProtected() to
modify that state, then it is a semantic error to call it from get(),
because as a const member function, get() promises not to modify that
state.

I wonder whether you're confusing the "const" modifier for variables
with the "const" modifier for member functions. Since it is an
interface sin to allow a member function with "get" in its name modify
object state without a darn good reason, I'd just make both methods
const and be done with it.

I would also avoid using C-style casts. If you must cast, use
const_cast, static_cast, or dynamic_cast. In this case, you don't need
to cast at all because C++ can append the "const" modifier without a
problem.

A more interesting way to accomplish your aim here might be to provide
the desired customization behavior as a policy given as a template
parameter. Just a thought.

Luke
 
A

Alex

The problem is that I want to use getProtected sometimes to modify the
value whose pointer is returned (set) and sometimes not (get).

I think it is the same problema as in this example:


class MyVector {
protected:
int& get(int i) {.... A LONG AND HARD PROCESSING ... }
public:
int& operator[](int i) { return get(i); }
const int& operator[](int i) const { return get(i); } // I
don't want to write twice get() code

};

Do you understad me now? I want to access a pointer in a const way when
needed and y a non-const way some times. I don't want my base classess
to redefine both methods, as I don't want in this example to write the
get() code twice.



}
 
B

Bob Hairgrove

The problem is that I want to use getProtected sometimes to modify the
value whose pointer is returned (set) and sometimes not (get).

I think it is the same problema as in this example:


class MyVector {
protected:
int& get(int i) {.... A LONG AND HARD PROCESSING ... }
public:
int& operator[](int i) { return get(i); }
const int& operator[](int i) const { return get(i); } // I
don't want to write twice get() code

};

Do you understad me now? I want to access a pointer in a const way when
needed and y a non-const way some times. I don't want my base classess
to redefine both methods, as I don't want in this example to write the
get() code twice.

For the const get() function, I would return the int by value, not by
reference. But the root of the problem is the const'ness of the object
itself. What are the circumstances where MyVector needs to be const?
Can you do without the const?

Maybe you could delegate the work done by get() into smaller
functions, then isolate the ones that get in the way of using const. A
reference is usually only returned from a function if there is a
member object available. That should involve zero processing, and in
fact such functions are usually inlined.
 
A

Alex

"What are the circumstances where MyVector needs to be const?
Can you do without the const? "


void f(const int& x);
void g(int& x);

....
MyVector v;
f(v[0]); // const
g(v[0]); // not const
....

But MyVector is just an example. I need to return a const pointer and a
non-const pointer. And I don't want the subclasses to redefine both,
but just one, as I explain in the first post.
 
B

BobR

Alex wrote in message
But MyVector is just an example. I need to return a const pointer and a
non-const pointer. And I don't want the subclasses to redefine both,
but just one, as I explain in the first post.

You can assign a non-const to a const, but, not a const to a non-const.

[ RW == Read-Write. RO == Read-Only ]

int o(0); // RW
int const oConst = 1; // must initialize a constant // RO
int *p = &o; // int is RW, pointer is RW
int const *pConst = &oConst; // int is RO, pointer is RW

pConst = p; // ok
pConst = pConst; // ok
p = p; // ok
// p = pConst; // won't compile (without a const_cast<>(). Think first!!)

// p is pointing to memory that can be *read* or written to.
*p = 43; // should be no problem. [ o == 43 ]

pConst = p; // should not cause a problem. the int *can* be read.
// *pConst = 43; // should cause a problem. "assignment of read-only
location"
// The 'int' is constant(RO) thru pointer, not the
pointer to it.

int * const pcConst = &o; // const pointer to an RW int.
// pcConst=p; // should cause a problem. the pointer is const.
// assignment of read-only variable `pcConst'
*pcConst = 43; // should not cause a problem. [ o == 43 ]

// int const * const pccConst( &oConst ); // ok
int const * const pccConst( &o ); // 'o' is RW
// pccConst = p; // nope. the pointer is const.
// *pccConst = 43; // nope. What it points to is RO thru pointer.


If you are the slightest bit light-headed on pointers, you should go get Mr.
Steinbach's tutorial:

-----Original Message-----
From: Alf P. Steinbach
Newsgroups: alt.comp.lang.learn.c-c++,comp.lang.c++,no.it.programmering.c++
Date: Thursday, December 08, 2005 12:04 AM
Subject: Finally, a release candidate of the "Pointers" document
(introduction to pointers)

http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01.pdf
http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01_examples.zip
 
A

Alex

I know all that about pointers and I know perfectly why my example
doesn't work (I haven't implemented it because I know what would
happen). I am asking for a design tip to do the same I want to do in my
example.
 
J

Jonathan Mcdougall

Alex said:
Hi. I'll try my problem with this example:

class C {
protected:
virtual int* getProtected(int index)=0;
public:
const int* get(int index) const
{ return (const int*) getProtected(index); }

virtual void set(int index, int value)
{ *getProtected(index) = value; }
...
};

class D : public C {
protected:
int* getProtected(int index) { ... }
};


I need a way to set a value and get a const pointer to that thing. I
want the base class to provide a standard way for set, which is just
copy the value. My approach is to make it easy: the child classes only
would need to implement getProtected and get() and set() will work ok.
If that class needs to do some extra processing when set() is called,
it can implement it, but otherwise it will work ok. getProtected is
protected to prevent to get a non-const pointer outside the class.

I don't know if you can understand me. Anyway, my problem is that that
doesn't work, because getProtected is a const member function and get()
is const.

Well in this case you're lying: getProtected() is non-const and you try
to call it from a const member function. If you were able to do that,
get() wouldn't be a const member function anymore. Shame on you.

There is no easy way to do that, except with const_cast, which you
should try to avoid. You could have getProtected() return by value
instead.

If getProtected() returns an address of a member object, forget it.
You'll have to duplicate the function. Isn't it possible to split
getProtected() into getCommon() for this to be easier?


Jonathan
 
L

Luke Meyers

Well, the only way I see to do it is to cast away the const at some
point. You can do it inside your setter, or inside getProtected prior
to returning it. That said, if it were me, I'd explore dozens of other
solutions before resorting to casting away const.

I did recently come up with a case where casting away const was exactly
the right thing to do. I had a vector< boost::shared_ptr<Foo> > as
member data to an object which provides a removeFooFromList method that
takes a boost::shared_ptr<Foo>. Since I'm not going to modify the Foo,
from an interface standpoint I should take a boost::shared_ptr<const
Foo>. But the vector doesn't recognize that as an is-a for its
contained type, so I had to cast off the const from inside the pointer
in order to do the removal. So, it does legitimately come up, but...
still leaves a nasty taste in one's mouth.

I'm still trying to come up with some funky solution for your problem
involving template magic, but no flash of inspiration so far.

Luke
 
N

Niklas Norrthon

Alex said:
I know all that about pointers

All what?
and I know perfectly why my example doesn't work

What example?
(I haven't implemented it because I know what would happen).
I am asking for a design tip to do the same I want to do in my
example.

To do what? I don't see any example. Please provide some context
when you post.

/Niklas Norrthon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top