Use of the const keyword in wxWidgets


The following is a discussion by Wolfgang Muees (wolfgang@wmsickte.escape.de) of the use of const in C++ programs, and in wxWidgets in particular.

Date: 18 Aug 1995 00:06:00 +0200
From: Wolfgang Muees 
To: J.Smart@ed.ac.uk
Subject: Re: precompiled headers

Yes, there is a problem with const ... you may modify the whole wxWin
from non-const to const at one time, and it will work. But if user
do subclassing of wxWin classes, they need to rework their code...

So for the purpose of defining default string arguments in header files,
you probably have to write

extern char * const xxx;
Procedure( ..., char * yyy = xxx);

so you will get your string in the data segment, not in the data segment.
I think some sort of #define to support const in new applications while
maintaining compatibility is really worth thinking of.







extern  char * const xxx;
Procedure( ...,  char * yyy = xxx);

So, new apps may set USE_CONST and benefit from it, old ones would
continue to work.

> I'd appreciate some more advice on consts, since now I've started
> putting them in I may as well do it properly to avoid future
> compatibility problems if I do it piece-meal.  I suppose all arguments
> to member functions and constructors, that aren't going to be changed
> by that function, should be const? I've always avoided const like
> the plague before because it's upset my code so much. Is there
> a way round this compatibility problem, or do you really have to be
> all-const or no-const? I could define compatibility functions
> but that would really increase the size of the toolkit and apps :-(
>
As I started using const, i uses it everywhere I could. But soon, I found  
that sometimes, there is nothing usefull in it.

An useful example:

typedef struct { bla bla bla } SomeLargeStruct;

Procedure( const SomeLargeStruct& inVar)
{
        
}

If for efficienty, you pass large data via reference, you can use "const"  
to ashure that the data is not changed inside the procedure. This is one  
of the very beneficial uses of "const". NOTE that if you use a pointer  
instead of a reference, you have to protect the code inside your procedure  
agains (pointer == NULL). So a reference will have less overhead and a  
simplier syntax because you omitt the "*".


Procedure( const bool inVar) { .... };

seems to be pretty useless for me... Don't make a simple parameter const  
which is passed by value ... it give you nothing, but you can't change the
value of "inVar" inside the Procedure any more.

For pointers, I use "const" to enforce that the pointer can't change the  
location it points to. I seldom use "const" to make the pointer itself
const. The only exception is if a pointer is only initialized to a given  
value and doesn't change.

Some special case: virtual methods and constructors. They are subject to  
be overridden in subclasses. If you make a parameter "const" in a base  
class, you enforce a limitation for all possible subclasses: no subclass  
may change the parameter any more. So think of the suggested usage of a  
parameter in subclasses before making him const.

Another usage are const member functions...

class time {
        int operator==( const time& rhs) const;
};

operator== is defined "const" because he may be invoked with const  
objects. This is very usefull for classes which are much like build-in  
data types. Note that the const version of operator== may also act on no- 
const objects. But if you have operators like [] or ->, where the return  
value of the operator is a reference to the (maybe) const object, you have  
to declare both const and non-const member functions.

const data members: they may only be initialized in the initializer list  
of the constructor. They can't change. Sometimes, I use this for assigning  
a class ID to a class.

const and inline: simple inline functions are often const:
class xyz {
private:
        int MyPrivateValue;
public:
        inline int GetValue(void) const { return MyPrivateValue; };
};

Using "const" in this context, don't give you a benefit ... unless you  
suppose to have const objects of class xyz!

So, to sum it up...
a) use const in new code
b) change the old code, using a #define, mainly to cure bugs and enhance
   performance.
c) Making every possible parameter and method const, should not worth the
   work.

The most I know of "const" is from Scott Meyers book "Effective C++".  
There is a discussion about using const.

A benefit of "const" not mentioned most times is that they are a partial  
cure to the pointer alias problem. Example:

const char * cp1 = ...;
const char * cp2 = ...;
...

...

In this example, it is not possible to change the contents of *cp1 and  
*cp2. So an optimasing compiler may held  *cp1 and *cp2 in registers and  
don't have to reload the values.

Regards
Wolfgang