The "const" and "mutable" keyword
- "const" means that the data related to the variable is to be left constant.
- Only constant functions can be called on a const object.
- "mutable" means that the data within a constant can be modified without changing the object ie the object is logically constant.
- "mutable" is often abused. Its correct use is to allow for things like access counters and other data items that are not directly related to the objects real data. For example making the size of a toy class mutable is an abusive usage.
- const tends to be referred to as a poison pill by in-experienced programmers who don't know about const_cast and how it works. Correct use of constants and const_cast can produce so very interesting coding patterns.
Constant Data, Pointers and references
const int value0 = 1; //constant data
const int* value1 = &value0; //a constant pointer
const int& value2 = value0; //a constant reference
- The Constant data indicates that the contents of the object or inbuilt type are not modifiable
- The Constant pointer and references define that the data the pointer refers to is constant
Pointers which are constant
char* const string = "abc"; //a pointer constant
- The Pointer Constant define that the pointer its self is not modifiable but the data is free to be messed with.
Const member functions
void function() const;
- When "const" is applied to member functions it means that the action of the function will not change the object.
- members of the object marked as "mutable" can me modified and maintain the "const" status of the object.
- Constant member functions can not return non-constant references to members of the constant class.
- Nothing prevents the constant member function from modifing items outside the objects local scope such as static members of the class.
- By extension a const member function can const_cast its own this pointer and then modify the non-const version of its self! And it can also return this to the outside world. Doing this is considered bad form however in some systems bad usage of const and mutable has made it a requirement.
#include <iostream>
using namespace std;
class BaseA
{
public:
static const int staticConstIntA = 0; //init in global
const int constA; //init in constructor
int intA;
static int staticA;
mutable int mutableA;
//const mutable int f; //BAD illogical
void setA_Const(int _in) const
{
//staticConstIntA = _in; //BAD const is hard set
//constA = _in; //BAD const is already hard set
staticA = _in;
//intA = _in; //BAD a const member is modifing the object
mutableA = _in;
}
void setA(int const _in)
{
//staticConstIntA = _in; //BAD const is hard set
//constA = _in; //BAD const is already hard set
staticA = _in;
intA = _in;
mutableA = _in;
}
//BAD a const member is directly returning a modifable piece of itself
//int& getA_Const(int _in) const
//{ return intA; }
int& getA_UnConst() const
{
BaseA* self = const_cast<BaseA*>(this);
self->intA = 10;
return self->intA;
}
BaseA(int _in) : constA(_in)
{
//staticConstIntA = _in; //BAD const is hard set
//constA = _in; //BAD const is already hard set
staticA = _in;
intA = _in;
mutableA = _in;
}
};
int BaseA::staticA;
int main()
{
// *********normal class*************** //
BaseA normalA(1);
//normalA.constA = 10; //BAD member is const
//BaseA::staticConstIntA = 10; //BAD member is const
normalA.intA = 1;
normalA.mutableA = 1;
normalA.setA(10);
normalA.setA_Const(10);
// *********constant class*************** //
const BaseA constA(3);
//constA.intA = 10; //BAD entire class is const making normal members also const
constA.mutableA = 10; //OK a mutable member can be modifed.
//constA.setA(10); //BAD member function is not const
constA.setA_Const(10); //GOOD member function is const, and modifing a const class
// *********constant refed class*************** //
const BaseA& refA = normalA;
//constA.intA = 10; //BAD entire class is const making normal members also const
refA.mutableA = 10; //OK a mutable member can be modifed.
//constA.setA(10); //BAD member function is not const
refA.setA_Const(10); //GOOD member function is const, and modifing a class static
// *********pointers to const class*************** //
BaseA* ptrA = new BaseA(2);
const BaseA* constPtrA = new BaseA(4);
//constPtrA->intA = 1; //BAD a const pointer means the DATA not the POINTER
constPtrA->mutableA = 1;
//constPtrA->setA(10); //BAD member function is not const
constPtrA->setA_Const(10); //GOOD member function is const, and modifing a const class
constPtrA = ptrA; //GOOD a const pointer means the DATA not the POINTER
//const BaseA* ptrB = new(constPtrA) BaseA(20); //BAD reinit constructors dont work on const pointers
// *********pointers which is const to class*************** //
BaseA* const ptrConstA = new BaseA(5);
ptrConstA->intA = 1; //GOOD a pointer const means the POINTER not the DATA
ptrConstA->mutableA = 1;
ptrConstA->setA(10); //GOOD a pointer const means the POINTER not the DATA
ptrConstA->setA_Const(10); //GOOD a pointer const means the POINTER not the DATA
//ptrConstA = ptrA; //BAD a pointer const means the POINTER not the DATA
const BaseA* ptrB = new(ptrConstA) BaseA(20); //GOOD reinit constructors DO work on pointers which are constant
// *********UNLOCKING the const posion pill*************** //
const BaseA constB(3);
cout << "before unlocking: " << constB.intA << endl;
int& unlockedA = constB.getA_UnConst();
cout << "after unlocking: " << constB.intA << endl;
}
No comments:
Post a Comment