I'm having some trouble with a particular piece of code, if anyone can enlighten me on this matter it would be greatly appreciated, I've isolated the problem down in the following sample:
#include <iostream>
using namespace std;
class testing{
int test();
int test1(const testing& test2);
};
int testing::test(){
return 1;
}
int testing::test1(const testing& test2){
test2.test();
return 1;
}
So what could possibly have cause the following error:
test.cpp:15: error: passing ‘const testing’ as ‘this’ argument of ‘int testing::test()’ discards qualifiers
Thanks a lot!
The problem is calling a non-const
function test2.test()
on a const
object test2
from testing::test1
.
testing::test1
gets test2
as a parameter const testing &test2
. So within testing::test1
, test2const
. Then in the first line of the function:
test2.test()
The testing::test
function is called on test2
. That function is not declared with const
at the signature end, so it may modify the object it is called on (the this
pointer implicitly passed to it), and even though it does not, the compiler assumes so. By letting you call it there, the compiler would let you modify a const
variable without an explicit cast, which C++ is not supposed to allow. Therefore to explain the error message:
test.cpp:15: error: passing ‘const testing’ as ‘this’ argument of ‘int testing::test()’ discards qualifiers
this
refers to the object the member function (testing::test
) operates on, and in this case it is not const
, because testing::test
was not declared with const
, and thus the mismatch is detected when trying to make a non-const
pointer (this
) refer to a const
object (testing
), ignoring the const
qualifier.
To solve this, decide whether the testing::test
function should ever need to modify the object it is called on (the way it is written now it does not, as all it does is return 1
, however that may change, so you need to think at what its intended functionality is). If it should, then obviously calling it on a const
object is bad, although you can use const_cast
to ask the compiler to override that, but this is dangerous. If it should not, then mark it const
, so that it can be called on const
objects as well:
class testing{
int test1() const;
// ...
}
int testing::test() const {
// ...
}
Because of the definition of the member function test1:
int testing::test1(const testing& test2){
test2.test();
return 1;
}
You are passing in a const reference of for the variable test2.
That means that you cannot modify any member of test2 and you cannot call any member function that is not const or is not static.
Here is how you can fix:
int testing::test() const {
return 1;
}
The extra const at the end tells the compiler that you are not planning on modifying the content of the current object (and if you do you will get a different compiling error).
The line:
test2.test()
is calling a non const function, even though test2 is a const reference. That's the problem. You can fix this by making testing::test a const function.
testing::test1(const testing& test2) is expecting the passed object to be const, and it will give you an error if you either modify the values of it's variables, or access any methods thereof that are not explicitly defined as const.
Since the test() method doesn't actually change any data, best practice is to set it const, as follows:
class testing{
int test() const;
int test1(const testing& test2);
};
int testing::test() const {
return 1;
}
Alternatively, just remove the word const when defining the arguments for test1(), and it will allow you to access any of the passed object's methods at your leisure.
For a quick and dirt solution, try compiling with -fpermissive
as often suggested by the compiler itself (which is probably what VisualStudio compilers do, being that Windows users seldom report this problem).