I know this has been asked a lot, but the only answers I could find was when the const-ness was actually casted away using (int*) or similar. Why isn't the const qualifier working on pointer type member variables on const objects when no cast is involved?
#include <iostream>
class bar {
public:
void doit() { std::cout << " bar::doit() non-const\n"; }
void doit() const { std::cout << " bar::doit() const\n"; }
};
class foo {
bar* mybar1;
bar mybar2;
public:
foo() : mybar1(new bar) {}
void doit() const {
std::cout << "foo::doit() const\n";
std::cout << " calling mybar1->doit()\n";
mybar1->doit(); // This calls bar::doit() instead of bar::doit() const
std::cout << " calling mybar2.doit()\n";
mybar2.doit(); // This calls bar::doit() const correctly
}
// ... (proper copying elided for brevity)
};
int main(void)
{
const foo foobar; // NOTE: foobar is const
foobar.doit();
}
The code above yields the following output (tested in gcc 4.5.2 and vc100):
foo::doit() const calling mybar1->doit() bar::doit() non-const <-- Why ? calling mybar2.doit() bar::doit() const
When a foo instance is const, its data members are const too, but this applies differently for pointers than you might at first think:
struct A {
int *p;
};
A const obj;
The type of obj.p is int * const, not int const *; that is, a constant pointer to int, not a pointer to constant int.
For another way to look at it, let's start with a function:
template<class T>
T const& const_(T const &x) {
return x;
}
Now imagine we have an A instance, and we make it const. You can imagine that as applying const_ on each data member.
A nc;
// nc.p has type int*.
typedef int *T; // T is the type of nc.p.
T const &p_when_nc_is_const = const_(nc.p);
// "T const" is "int * const".
const T &be_wary_of_where_you_place_const = const_(nc.p);
// "const T" is "int * const".
// "const T" is *not* "const int *".
The variable be_wary_of_where_you_place_const shows that "adding const" is not the same as prepending "const" to the literal text of a type.