I have the following test code:
class A
{
public:
void funcA()
{
std::cout << "banana" << std::endl;
}
};
class B
: public A
{
public:
A t;
void funcB() const
{
t.funcA();
}
};
int main(int argCount, char *args[])
{
B tst;
tst.funcB();
}
Where funcA
does not have a const
definition and funcB
has a const
definition.
When compiling the code, I get the error:
passing ‘const A’ as ‘this’ argument discards qualifiers [-fpermissive]
This should happen because I am calling inside a const
function a non-const
function.
However, when I do:
class B
: public A
{
public:
A* t;
void funcB() const
{
t->funcA();
}
};
The code compiles and works. Why is that? I am just compiling with g -g main.cpp
, and I missing flags for this? or is this behavior to be expected?
CodePudding user response:
You're not modifying the pointer member variable, you're modifying the value that it is pointing to, so it compiles.
The t
variable is a pointer that points to a variable of type A
. Doing t->funcA();
may change the value that the variable points to, but it does not change the pointer member itself, which is all the compiler is required to enforce here.
If you modified the actual pointer like this, this function would not compile.
void funcB() const
{
t = nullptr; //Will not compile
}
If you want to prevent someone from modifying the A variable through the pointer, simply declare the pointer as const. This will prevent modifying the value it points to.
const A* t;
CodePudding user response:
Case I: Explaination of your 1st code snippet
When we write
void funcA();
this means funcA()
has a implicit parameter whose type is A *const
i.e., a const pointer to a non const A object. This in turn means we can call this function only on nonconst A objects. If you try to call this member function on a const A object you will get the mentioned error.
For showing my point lets try to call funcA
on a const A object. The code is as follows:
#include <iostream>
class A
{
public:
void funcA()
{
std::cout << "banana" << std::endl;
}
};
int main()
{
A nonconstobject;
nonconstobject.funcA(); //this works
const A constobject; //note the const here
constobject.funcA(); //this gives error: passing ‘const A’ as ‘this’ argument discards qualifiers
}
The above snippet gives the same error as you mentioned as can be seen here.
And this exactly what happens in your 1st code snippet. Now i am going to explain in steps what happens in your 1st code snippet:
Step 1. You have funcB();
declarared as const member function. Which means its own implicit parameter has type const B *const
i.e., a const pointer to const B object. This in turn means the data members(including data member t) of B are themselves const.
Step 2. Now since t
is const
and as i said in my custom example, you can't call a nonconst member function on a const object. So you get your mentioned error.
Case 2: Explaination of your 2nd code snippet
In the second case you have changed the data member t
to be of type A*
that is a pointer to A object.
Now lets look at in steps what happens in this case:
Step 1. You have funcB();
declarared as const member function. Which means its own implicit parameter has type const B *const
i.e., a const pointer to const B object. This in turn means the data members(including data member t) of B are themselves const. The difference this time is that t
will become a const pointer to A i.e., t
is of type A* const
Step 2. Again funcA
has implicit parameter that is of type A *const
since funcA
is not a const member function. And this type exactly matches with what you pass using the call t->funcA();
. So you don't get any error in this case.