By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,070 Members | 1,718 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,070 IT Pros & Developers. It's quick & easy.

What is the second const used for?

P: n/a
I have searched and not found an answer to this question. I ran upon
the following statement in a *.cpp file in a member function:

static const char * const pacz_HTMLContentTypeHeader = "Content-Type:
text/html\r\n";

Why is the second const needed and what does it do?

Thanks

Gary

Feb 7 '07 #1
Share this Question
Share on Google+
4 Replies


P: n/a
gr*****@yahoo.com wrote:
I have searched and not found an answer to this question. I ran upon
the following statement in a *.cpp file in a member function:

static const char * const pacz_HTMLContentTypeHeader = "Content-Type:
text/html\r\n";

Why is the second const needed and what does it do?
'const' makes the adjacent type constant. In your case, the 'const'
between 'static' and 'char' makes 'char' constant (immutable). The
other 'const' (right after the asterisk) makes the adjacent type
(which is 'a pointer to const char') immutable.

The other way is to learn to read declarations. In your case the
object 'pacz_HTMLContentTypeHeader' is [going to the right, seeing
the end of the declaration, proceeding to the left] a const [the
asterisk] pointer to char [which is] const, and the lifetime is
static.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Feb 7 '07 #2

P: n/a
Here is an explanation on const that I created for my C++ students (it
should answer most of your const questions):

The purpose of the const keyword is to prevent accidental or
unintentional change of a value.

Let us examine some examples of using the const keyword and the types
of errors that will be generated, if we try to circumvent the
protection offered by the const keyword. Note that all error messages
displayed were generated by MS Visual Studio .NET 2003.

Example 1:

const int x = 10; // const protects x from being modified.
// x must be initialized, or a compile error
// will be generated.
x = 5; // This is NOT allowed. Compiler error generated follows below.

error C2166: l-value specifies const object
Example 2:

// Note that this function does not actually modify y
void func(int & y)
{
return;
}

int main()
{
const int x = 10; // const protects x from being
// modified.
func(x); // This is NOT allowed.
}

error C2664: 'func' : cannot convert parameter 1 from 'const int' to
'int &'

This error is generated because func() is not "promising" to not
change x's value. It does not matter that the function does not
actually change x's value.

If the function prototype was instead:

void func( const int & y); // or
void func( int const & y); // the order of const and int does not
// matter

there would be no compile error. Now the function is promising to not
change x's value through the use of the const keyword.

This is another reason why we should attempt to make parameters of a
function const, so that the function can accept both const and non-
const arguments.

If the function prototype was instead:

void func( int y);

there would also be no compile error. Why? Because now y is being
passed call by value, rather than call by reference, so we don't care
if the function changes the argument.

Example 3:

int x = 10;
int y = 20;
const int *xPtr; // may NOT use pointer to modify value, but may
// let pointer point to another address

xPtr = & x; // this is allowed
xPtr = & y; // and this is allowed as well

*xPtr = 50; // This is NOT allowed. Attempting to dereference
// the pointer and change the value at that address.

error C2166: l-value specifies const object
Example 4:

int x = 10;
int y = 20;
int * const xPtr = &x; // may use pointer to modify value, but
// may NOT let pointer point to another address

xPtr = & y; // This is NOT allowed.

*xPtr = 50; // But this is allowed.

error C2166: l-value specifies const object

Notice that in this example, xPtr must be initialized when it is
declared, while in the previous example it was not necessary to do so.

Example 5:

int x = 10;
int y = 20;
const int * const xPtr = &x; // may NOT use pointer to modify
// value, and may NOT let pointer point to another address

xPtr = &y; // This is NOT allowed

*xPtr = 50; // This is NOT allowed either

error C2166: l-value specifies const object
error C2166: l-value specifies const object

This last example is simply Example 3 & 4 combined.

Note that in the following function prototype, zPtr is being offered
the exact same protection as xPtr in the above example.

void func( const int * const zPtr);

Do you think the xPtr from above could be passed to a function with
the following prototype?

void func(const int * iPtr);

Yes it can! Surprised? It is because, similar to what was discussed in
Example 2 above, iPtr is being passed call by value. Now, if instead
we had the following function prototype.

void func(const int *& iPtr);

Now iPtr is being passed call by reference, and therefore the compiler
would complain if we tried to pass xPtr to this function. Of course
xPtr could be passed to the following function with no problem.

void func(const int * const & iPtr);

Example 6:

class myClass {
public:
void memFunc(myClass & obj2) const // This const protects the
// object invoked with this method.
{
obj2.dataMem = 10; // Object obj2 is not protected by
// making memFunc() const. No error will be generated.
this->dataMem = 10; // This is NOT allowed.
}
private:
int dataMem;
};

int main()
{
myClass x,y;
x.memFunc(y);
return 0;
}

error C2166: l-value specifies const object
Example 7:

class myClass {
public:
const int & memFunc(int & iRef) // This const protects the
// reference being returned by the method.
{
return iRef;
}
private:
int dataMem;
};

int main()
{
int y;
myClass x;
x.memFunc(y) = 10; // This is NOT allowed. We are trying to
// change the reference being returned by memFunc().
return 0;
}

error C2166: l-value specifies const object

Would the following change to main() also generate an error?

int & z = x.memFunc(y);

The answer is yes! Not because we are trying to modify the reference
returned by memFunc(), but because we are assigning that reference to
another reference which is not const. The following statement would
be ok.

const int & z = x.memFunc(y);

Now z is a const reference, and is "promising" to not modify the const
reference being assigned to it.

Would the following statement also generate an error?

int z = x.memFunc(y);

No. In this case, only a copy of the reference being returned by
memFunc() is assigned to z. Modifying z will not modify the reference
which was returned by memFunc().
Example 8:

This example is actually an extension of Example 2.

void func(const int & val) // This const protects val from being
// modified inside this function.
{
val = 20; // This is NOT allowed.
}

int main()
{
int x =10;
func(x);
return 0;
}

error C2166: l-value specifies const object

In case you are wondering, even if val were passed to func() as a call
by value rather than as a call by reference, val may still NOT be
modified inside of func().

Example 9:

class myClass {
public:
myClass (void) { //default ctor
this->year = 1970;
this->month = 1;
this->day = 1;}
myClass (int y, int m = 1, int d = 1){ // conversion ctor
this->year = y;
this->month = m;
this->day = d; }

void memFunc (){} // non const member function does nothing

private:
int year;
int month;
int day;
};

int main()
{
const myClass defaultObj; // use default ctor
// to create const object
const myClass bDay(1956,04,25); // create a second const object

defaultObj.memFunc();// This is NOT allowed since
// memFunc() is not const
bDay.memFunc();// This is NOT allowed since
// memFunc() is not const

return 0;
}

error C2662: 'myClass::memFunc' : cannot convert 'this' pointer from
'const myClass' to 'myClass &'

error C2662: 'myClass::memFunc' : cannot convert 'this' pointer from
'const myClass' to 'myClass &'

If we wish to create a const object of a user defined class, we must
have a constructor that can initialize the object exactly as we need
it to be, since we will not be able to modify the object after it has
been "constructed".

Note that in the sample code above, if we had declared the 3 data
members to be public instead of private, we would still not have been
able to change the value of the members of the defaultOBJ and bDay
objects in main(), because these objects are const.
Miscellaneous Point 1:

The following will generate some compile errors.

int main()
{
int SIZE = 10; // SIZE is not const
int y[SIZE]; // SIZE is not a constant, so NOT allowed.
return 0;
}

If we make SIZE const, the compiler is now happy.

int main()
{
const int SIZE = 10; // SIZE is now const
int y[SIZE]; // SIZE is now a constant, so it is allowed.
return 0;
}
Miscellaneous Point 2:

We are normally not allowed to initialize a data member inside a class
declaration in C++. One exception is a const static data member of
integral type. By integral type we mean types char, short, int, long
or long long. Type double for example is NOT an integral type. Below
is a code snippet showing a valid example:

class myClass {
private:
const static int SIZE = 100; //class variable
int dataArray[SIZE]; //use class variable declared and
// initialized in previous statement
...

Again, I stress that the above example works only because SIZE is
static, const and an integral type.

Miscellaneous Point 3:

What is wrong with the following code example?

class myClass {
public:
int & memFunc(const int & iRef)
{
return iRef;
}
private:
int dataMem;
};

int main()
{
const int y = 10;
myClass x;
x.memFunc(y);
return 0;
}

Here is a hint. This code will generate the following compile error.

error C2440: 'return' : cannot convert from 'const int' to 'int &'

The problem is that memFunc() is trying to return iRef as a non const
reference. To make the error go away, we must either return a non
reference or make the returned reference const.
That pretty well covers my introduction to the use of const. Remember
that one of the traits of a good C++ programmer is that they use const
where ever possible in their code. In the long run, such a practice
will pay real dividends.

Feb 7 '07 #3

P: n/a
Victor Bazarov wrote:
gr*****@yahoo.com wrote:
>I have searched and not found an answer to this question. I ran upon
the following statement in a *.cpp file in a member function:

static const char * const pacz_HTMLContentTypeHeader = "Content-Type:
text/html\r\n";

Why is the second const needed and what does it do?

'const' makes the adjacent type constant. In your case, the 'const'
between 'static' and 'char' makes 'char' constant (immutable). The
other 'const' (right after the asterisk) makes the adjacent type
(which is 'a pointer to const char') immutable.

The other way is to learn to read declarations. In your case the
object 'pacz_HTMLContentTypeHeader' is [going to the right, seeing
the end of the declaration, proceeding to the left] a const [the
asterisk] pointer to char [which is] const, and the lifetime is
static.
Or to simplify, the first const says you can't modify the char data
through pacz_HTMLContentTypeHeader, and the second const says you can't
change *where* pacz_HTMLContentTypeHeader points to.
Feb 7 '07 #4

P: n/a
gr*****@yahoo.com wrote:
I have searched and not found an answer to this question. I ran upon
the following statement in a *.cpp file in a member function:

static const char * const pacz_HTMLContentTypeHeader = "Content-Type:
text/html\r\n";

Why is the second const needed and what does it do?
Here is a (very) succint summary of const as it applies to pointers:
http://www.parashift.com/c++-faq-lit....html#faq-18.5

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Feb 8 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.