What is the meaning of const
in declarations like these? The const
confuses me.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
What is the meaning of const
in declarations like these? The const
confuses me.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
The const means that the method promises not to alter any members of the class. You'd be able to execute the object's members that are so marked, even if the object itself were marked const
:
const foobar fb;
fb.foo();
would be legal.
See How many and which are the uses of “const” in C++? for more information.
These const mean that compiler will Error if the method 'with const' changes internal data.
class A
{
public:
A():member_()
{
}
int hashGetter() const
{
state_ = 1;
return member_;
}
int goodGetter() const
{
return member_;
}
int getter() const
{
//member_ = 2; // error
return member_;
}
int badGetter()
{
return member_;
}
private:
mutable int state_;
int member_;
};
The test
int main()
{
const A a1;
a1.badGetter(); // doesn't work
a1.goodGetter(); // works
a1.hashGetter(); // works
A a2;
a2.badGetter(); // works
a2.goodGetter(); // works
a2.hashGetter(); // works
}
Read this for more information
The const qualifier means that the methods can be called on any value of foobar. The difference comes when you consider calling a non-const method on a const object. Consider if your foobar type had the following extra method declaration
class foobar {
...
const char* bar();
}
The method "bar" is non-const and can only be accessed from non-const values.
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
The idea behind const though is to mark methods which will not alter the internal state of the class. This is a powerful concept but is not actually enforcable in C++. It's more of a promise than a guarantee. And one that is often broken and easily broken.
foobar& fbNonConst = const_cast<foobar&>(fb1);
Blair's answer is on the mark.
However note that there is a mutable
qualifier which may be added to a class's data members. Any member so marked can be modified in a const
method without violating the const
contract.
You might want to use this (for example) if you want an object to remember how many times a particular method is called, whilst not affecting the "logical" constness of that method.
When you add the const
keyword to a method the this
pointer will become const, and you can therefore not change any member code. (Unless you use mutable
, more on that later).
The const
keyword is part of the functions signature which means that you can implement two similar methods, one which is called when the object is const, and one that isn't.
#include <iostream>
class ConstClass
{
private:
int counter = 0;
public:
void Foo()
{
std::cout << "Foo" << std::endl;
}
void Foo() const
{
std::cout << "Foo const" << std::endl;
}
};
int main(void)
{
ConstClass* cc = new ConstClass();
const ConstClass* ccc = cc;
cc->Foo();
ccc->Foo();
delete cc;
ccc = null;
return 0;
}
This will output
Foo
Foo const
In the non-const method you can change the instance members, which you cannot do in the const version. If you change the method declaration in the above example to the code below you will get some errors.
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
This is not completely true, because you can mark a member as 'mutable' and a const method can then change it. It's mostly used for internal counters and stuff. The solution for that would be the below code.
#include <iostream>
class ConstClass
{
private:
mutable int counter;
public:
ConstClass() : counter(0) {}
void Foo()
{
counter++;
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++;
std::cout << "Foo const" << std::endl;
}
int GetInvocations() const
{
return counter;
}
};
int main(void)
{
ConstClass* cc = new ConstClass();
const ConstClass* ccc = cc;
cc->Foo();
ccc->Foo();
printf("The ConstClass instance has been invoked %d times\n",
ccc->GetInvocations());
delete cc;
ccc = NULL;
return 0;
}
which would output
Foo
Foo const
The ConstClass instance has been invoked 2 times