const keyword in C++

This is somehow the second part of my previous post regarding const keyword. To be honest recently I dealt with some problems in using it and I thought useful to look into some valuable resources to get more insight knowledge.

In my previous post I tried to outline some of const qualifier subtilities and in this post I want to continue and to extend a little bit this attempt.

A good point to start this discussion is to trace one difference between C and C++: in C default linkage type is external and in C++ it is internal.

This means that in C a variable defined in one translation unit (source file + its corresponding headers) is visible across the entire program. If you want to restrict this you have to declare the global variables as static.

In C header files do not contain definitions. This is to prevent having more definitions for the same variable (header files can be included in many source files, so more definitions for a single variable can be seen across the program).

This is not the case in C++ where header files usually contain class definitions and can also contain const definitions. In C++ the default linkage type is internal, you are free to write definitions in header files which will be included in many other sources, but this won’t generate any definition collisions.

Another important thing to discuss is that const qualifier can also be applied to functions (well … this is not specific to C++).  It can be a parameter or a returned value. Here there are three possibilities: the parameters can be passed by value, by reference or by pointers. First case does not really matters because the function, when it is called, will make a copy of the arguments and will act on this copy, not on the original (remember the notorious example with swap function).

In case of last two methods of passing arguments this is indeed effective. Const modifier assures that the variables that either the pointer or the reference is “referring” cannot be changed and this is an important thing to be taken into consideration.

const char* function (const char *s)
{
return *(s+1); //function is not changing the char string that s is pointing to
} //and is returning second character in the string

Another C++ specific aspect of const keyword, is that it can be applied to functions’ body. It is something like this:

int capacity() const; //declaration
int capacity() const //definition
{

}

This has been introduced due to the object-oriented nature of C++, as long as in C const could be applied on primitive data types, it has to be applied also on user-defined types in C++. It is worthwhile to say that there are other largely used object-oriented languages such as Java or C#, where this keyword is not present (well there is a workaround mechanism but as far as I remember slightly different).  The programmer has so the possibility to lock objects and also data members, from being modified. If you declare a member function as const the object will not be modified by that function.

If we are talking about const objects and const methods there are some rules which dictates which one can act on which one.  This rule says:

const methods can be called by const and non-const objects alike, non-const methods can only be invoked by non-const objects.

The most notorious example in this case is concerning Set and Get methods:
class C
{
int i;
public:
int Get() const // Get can be const because is reading data members
{ return i; }
void Set(int j) // Set cannot be because is attempting to change data members
{ i = j; }
};

So if you are developer of a class and you code it for your customer, const methods are a way to guarantee that when calling them, the ’state’ of the object will not change.

// this part is already known -----
class C
{
int i;
public:
int Get() const
{ return i; }
void Set(int j)
{ i = j; }
};
// --------------------------------
void Foo(C& nonConstC, const C& constC) //references were taken as parameters
// in order to highlight the issue, passing by const value wouldn't make much sense in this context
{
int y = nonConstC.Get(); // OK, Get is const and can be applied to a non-const reference
int x = constC.Get();       //still OK, this is the first rule

nonConstC.Set(10); // OK - this is the common case
constC.Set(10); // ERROR - rule 2 "non-const objects can be called only by non-const methods"
}

There is a workaround to solve this: programmer can supply two overloaded methods in order to access both types of objects (actually here the discussion is about const or non-const referencs to objects):

class C
{
int i;
public:
int Get() const
{ return i; }
void Set(int j) //cannot be applied to const objects
{ i = j; }
void Set(int j) const // can be applied to const objects
{ return j; }
};

In this case when

constC.Set(10);

has to be executed, the compiler will have to choose the right Set method to access const or nonConst references.

What may come next after this? Volatile, mutable, const_cast operator …. what are they? how can they affect the const-ness of an object?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: