I would like to know if its possible to call a non-const member function from a const member function. In the example below First gives a compiler error. I understand why it
Overload on const
:
const int& Second() const
{
return m_bar;
}
You can add this method and keep the original non-const version.
The restriction of const member methods are came from compile time. If you can fool the compiler, then yes.
class CFoo
{
public:
CFoo() {m_Foo = this;}
void tee();
void bar() const
{
m_Foo->m_val++; // fine
m_Foo->tee(); // fine
}
private:
CFoo * m_Foo;
int m_Val;
};
This actually abolishes the purpose of const member function, so it is better not to do it when design a new class. It is no harm to know that there is a way to do it,especially it can be used as an work-around on these old class that was not well designed on the concept of const member function.
iterators are similar in this and make an interesting study.
const iterators are often the base for 'non const' iterators, and you will often find const_cast<>()
or C style casts used to discard const from the base class with accessors in the child.
Edit: Comment was
I have a zip iterator where the const one inherits from the non-const
This would generally be the wrong inheritence structure (if your saying what I think you are), the reason being that children should not be less restrictive than parents.
say you had some algorithm taking your zip iterator, would it be appropriate to pass a const iterator to a non const ?
if you had a const container, could only ask it for a const iterator, but then the const iterator is derived from an iterator so you just use the features on the parent to have non const access.
Here is a quick outline of suggested inheritence following the traditional stl model
class ConstIterator:
public std::_Bidit< myType, int, const myType *, const mType & >
{
reference operator*() const { return m_p; }
}
class Iterator : public ConstIterator
{
typedef ConstIterator _Mybase;
// overide the types provided by ConstIterator
typedef myType * pointer;
typedef myType & reference;
reference operator*() const
{
return ((reference)**(_Mybase *)this);
}
}
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
typedef std::reverse_iterator<Iterator> ReverseIterator;
return (const_cast<Foo*>(this))->Second();
Then cry, quietly.
It is possible:
const int& First() const
{
return const_cast<Foo*>(this)->Second();
}
int& Second() { return m_bar; }
I wouldn't recommend this; it's ugly and dangerous (any use of const_cast
is dangerous).
It's better to move as much common functionality as you can into helper functions, then have your const and non-const member functions each do as little work as they need to.
In the case of a simple accessor like this, it's just as easy to return m_bar;
from both of the functions as it is to call one function from the other.
I found myself trying to call a non-const member function that was inherited, but was actually const because of the API I was using. Finally I settled on a different solution: re-negotiate the API so that the function I inherit is properly const.
It won't always be possible to negotiate changes to others' functions, but doing so when possible seems cleaner and nicer than needing to use const_cast and it benefits other users as well.