From: Christian Christmann on
Hi,

I've some problems with the const-ness of objects.

Let's say I've an object A that contains a function:

const char *A::GetMnem()

Now I want to pass this object to a function of
another class B as a 'const' object:

int B:test( const A* ) {
...
string str = A->GetMnem();
....
}

Compiling this code, I get the error message:

test.cc:563: error: passing `const A' as `this' argument of `
const char* A::GetMnem()' discards qualifiers


Why?
Function 'test' of class 'B' does not attempt to modify passed object 'A',
so why is there a problem with 'const'? Declaring argument 'A' of 'test'
as a non-const object works fine.

Regards,
Chris


From: Mark P on
Christian Christmann wrote:
> Hi,
>
> I've some problems with the const-ness of objects.
>
> Let's say I've an object A that contains a function:
>
> const char *A::GetMnem()
>
> Now I want to pass this object to a function of
> another class B as a 'const' object:
>
> int B:test( const A* ) {
> ...
> string str = A->GetMnem();
> ....
> }
>
> Compiling this code, I get the error message:
>
> test.cc:563: error: passing `const A' as `this' argument of `
> const char* A::GetMnem()' discards qualifiers
>
>
> Why?
> Function 'test' of class 'B' does not attempt to modify passed object 'A',

Says you, but how should the compiler know this? The compiler sees that
function GetMnem (called by test) is *not* declared a constant function
and therefore makes no assumptions about what effect that function may
have on your A object. (Consider separate compilation, where the
compiler may not be able to see the definition of GetMnem when compiling
B::test.)

If GetMnem really doesn't modify A, declare it as:

const char* A::GetMnem () const;

If it does modify A, then you can't call it on a const A object.

-Mark

From: LR on
Christian Christmann wrote:
> Hi,
>
> I've some problems with the const-ness of objects.
>
> Let's say I've an object A that contains a function:
>
> const char *A::GetMnem()
>
> Now I want to pass this object to a function of
> another class B as a 'const' object:
>
> int B:test( const A* ) {
> ...
> string str = A->GetMnem();
> ....
> }
>
> Compiling this code, I get the error message:
>
> test.cc:563: error: passing `const A' as `this' argument of `
> const char* A::GetMnem()' discards qualifiers
>
>
> Why?
> Function 'test' of class 'B' does not attempt to modify passed object 'A',
> so why is there a problem with 'const'? Declaring argument 'A' of 'test'
> as a non-const object works fine.

Perhaps because you're calling a non const member function of A. I
don't think that it matters that you're calling it from a member of B.

Or perhaps because A is a class, not an instance, and to call GetMnem()
you have to pass a parameter that is a pointer to an instance of the
class and use that pointer to call GetMnem():
... B::test(const A *p) ...
... p->GetMnem(); ...
Unless GetMnem is static...
... A::GetMnem() ;...

Consider this untested uncompiled code:

class A {
public:
void f1();
void f2() const;
};

int main() {

A a1;
a1.f1(); // ok, a1 isn't const
a1.f2(); // ok, const guarantees that we won't change a1

const A a2;
a2.f1();
// oops, not ok a2 is const, but f1() isn't,
// ie f1 might try to change a2
a2.f2(); // ok, f2 is const and won't change a2

}

Now considering your code...

int B:test( const A *pointerToInstanceOfA) {
// pointerToInstanceOfA is a pointer to a const instance of A
//
// must remember to check to see if pointer is null or not!
const std::string str = pointerToInstanceOfA->GetMnem();
}

perhaps your GetMnem function could be const?

const char *A::GetMnem() const {
// it sort of worries me that you're returning a pointer here
// but....
static char x;
return &x;
}

I tend not to like pointers as paramters, so is it possible that you
could do this instead?
int B:test(const A &referenceToInstanceOfA) {
// pointerToInstanceOfA is a refeerence to a const instance of A
const std::string str = referenceToInstanceOfA.GetMnem();
return 0;
}

Oh, and since it very much looks like we're not changing B in B::test,
or at least we're not that snippet, perhaps B::test could be const too?
int B::test(const A &a) const {
const std::string str = a.GetMnem();
return 0;
}

BTW, is bool the return type you wanted to use, since your function name
is test, and very often that leads to either a true or false kind of
situation?

bool B::test(const A &a) const {
const std::string str = a.GetMnem();
// maybe we should test for something?...
const bool result = str == std::string("!");
return result;
}

I hope the above is clear, but if it isn't please let me know.

LR
From: Christian Christmann on
On Thu, 15 Jun 2006 17:54:27 +0000, Mark P wrote:

> Says you, but how should the compiler know this? The compiler sees that
> function GetMnem (called by test) is *not* declared a constant function
> and therefore makes no assumptions about what effect that function may
> have on your A object. (Consider separate compilation, where the compiler
> may not be able to see the definition of GetMnem when compiling B::test.)
>
> If GetMnem really doesn't modify A, declare it as:
>
> const char* A::GetMnem () const;
>
> If it does modify A, then you can't call it on a const A object.

OK, thank you.
A general question:

Let's say I've a function
void A:foo( B *b, C *c ) const;

What exactly does this "const" mean?
That an object of class A will not be modified by this function?
Is it still permitted to change objects 'b' and 'c'?

Thank you.

Chris
From: Mark P on
Christian Christmann wrote:
> On Thu, 15 Jun 2006 17:54:27 +0000, Mark P wrote:
>
>> Says you, but how should the compiler know this? The compiler sees that
>> function GetMnem (called by test) is *not* declared a constant function
>> and therefore makes no assumptions about what effect that function may
>> have on your A object. (Consider separate compilation, where the compiler
>> may not be able to see the definition of GetMnem when compiling B::test.)
>>
>> If GetMnem really doesn't modify A, declare it as:
>>
>> const char* A::GetMnem () const;
>>
>> If it does modify A, then you can't call it on a const A object.
>
> OK, thank you.
> A general question:
>
> Let's say I've a function
> void A:foo( B *b, C *c ) const;
>
> What exactly does this "const" mean?
> That an object of class A will not be modified by this function?
> Is it still permitted to change objects 'b' and 'c'?

More precisely, "the" object of class A will not be modified by this
function. That is, a non-static member function of class A is always
called by an object of class A, and that particular object is not modified.

To illustrate this, consider:

A a1;
A a2;

void A::foo (A& bar) const {...}

a1.foo(a2); // may modify a2, will not modify a1

-Mark