Const Qualifier question

M

Mahesh Tomar

Dear Readers,
I am porting my existing C code to C++. In my existing code
there are numerous functions that has been defined with CONST
qualifier. For eg. foo(const DATA_TYPE *x); DATA_TYPE is some typedef
structure and offcourse x is a pointer to it. Needless to say my
intention for writing such functions in C was to protect the accident
write to x's content. So far so good. While porting to C++, I've mada
DATA_TYPE as class and I want to retain the sanity of existing C
function that has Const qualifier. However am having some trouble,
which is illustrated in the sample code below :

#include <iostream>
typedef struct _temp {
int a;
char b;
short int c;
}TEMP_STRUCT; // Define some temporary structure for illustration
purpose

class data_type
{
public :
void *address;
data_type(void);
~data_type();
void init_data_type();
void * getAddress() ;
};

data_type::data_type()
{
address = new TEMP_STRUCT;
}
inline void * data_type::getAddress()
{
return((void *)address);
}
inline void data_type::init_data_type()
{
address->a=1;
address->b='a';
address->c=1;
};

void foo(const data_type *);

#define GET_ADDRESS(object) ((object)->getAddress())

int main(int argc, char *argv[])
{
data_type temp_object;
temp_object.init_data_type();
foo(&temp_object);
}
void foo(const data_type *temp_object)
{
using namespace std;

if (((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a)
cout << "Test Passed";
//Error error: passing `const
//data_type' as `this' argument of `void* data_type::getAddress
//()' discards qualifiers
}

In C functions like foo() were called with "const TEMP_STRUCT *"
argument therefore compiler took care of any accident write to its
content. However in C++ this argument is changed to a class, which
fetches the address to TEMP_STRUCT, however, I still want the class to
return the address in such a way that the content of address can't be
modified inside the function. However, above sample code doesn't work
because foo is called with const qualifier, therefore complier
complains, if I try to access any of its member function. However if
get_address is defined as " void * getAddress() const", the compiler
error goes away, however, const qualifier inside foo also looses its
meaning i.e. you can write to the content of data type.
My question is how can this class return address whose content can't
be modified and at the same time I dont have to change the prototype
of my existing C functions.
Am sorry, if this question doesn't belong here or the information I've
provided is not sufficient.
Thanks for your time,
Mahesh
 
M

Mike Wahler

See below.
Dear Readers,
I am porting my existing C code to C++. In my existing code
there are numerous functions that has been defined with CONST
qualifier. For eg. foo(const DATA_TYPE *x); DATA_TYPE is some typedef
structure and offcourse x is a pointer to it. Needless to say my
intention for writing such functions in C was to protect the accident
write to x's content. So far so good. While porting to C++, I've mada
DATA_TYPE as class and I want to retain the sanity of existing C
function that has Const qualifier. However am having some trouble,
which is illustrated in the sample code below :

#include <iostream>
typedef struct _temp {
int a;
char b;
short int c;
}TEMP_STRUCT; // Define some temporary structure for illustration
purpose

class data_type
{
public :
void *address;
data_type(void);
~data_type();
void init_data_type();
void * getAddress() ;

void *getAddress() const;
};

data_type::data_type()
{
address = new TEMP_STRUCT;
}
inline void * data_type::getAddress()

inline void * data_type::getAddress() const
{
return((void *)address);
}
inline void data_type::init_data_type()
{
address->a=1;
address->b='a';
address->c=1;
};

void foo(const data_type *);

#define GET_ADDRESS(object) ((object)->getAddress())

int main(int argc, char *argv[])
{
data_type temp_object;
temp_object.init_data_type();
foo(&temp_object);
}
void foo(const data_type *temp_object)
{
using namespace std;

if (((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a)
cout << "Test Passed";
//Error error: passing `const
//data_type' as `this' argument of `void* data_type::getAddress
//()' discards qualifiers
}

Look up 'const member function'.

-Mike
 
M

Mahesh Tomar

Mike,
Thanks for your time. However, I too have mentioned the solution in
my original e-mail where I stated "if member function,get_address, is
defined as " void * getAddress() const", the compiler error goes away,
however, const qualifier inside foo also looses its meaning i.e. you
can write to the content of data type."
Putting a const qualifier at the end of function will make the error
go away, however, if I do something like this
void foo(const data_type *temp_object)
{
using namespace std;

// This statement below will modify the content of temp_object and
that is
// not the intention.
((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a = 2;
cout << ((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a;
}
If you see above, the intent of foo () function which was suppose to
protect any accidental write to the content of temp_object is lost. In
short I want to maintain the sanity of such functions (that am porting
to C++).
Any insight into this will be really appreciated.

Thanks,
Mahesh

Mike Wahler said:
See below.
Dear Readers,
I am porting my existing C code to C++. In my existing code
there are numerous functions that has been defined with CONST
qualifier. For eg. foo(const DATA_TYPE *x); DATA_TYPE is some typedef
structure and offcourse x is a pointer to it. Needless to say my
intention for writing such functions in C was to protect the accident
write to x's content. So far so good. While porting to C++, I've mada
DATA_TYPE as class and I want to retain the sanity of existing C
function that has Const qualifier. However am having some trouble,
which is illustrated in the sample code below :

#include <iostream>
typedef struct _temp {
int a;
char b;
short int c;
}TEMP_STRUCT; // Define some temporary structure for illustration
purpose

class data_type
{
public :
void *address;
data_type(void);
~data_type();
void init_data_type();
void * getAddress() ;

void *getAddress() const;
};

data_type::data_type()
{
address = new TEMP_STRUCT;
}
inline void * data_type::getAddress()

inline void * data_type::getAddress() const
{
return((void *)address);
}
inline void data_type::init_data_type()
{
address->a=1;
address->b='a';
address->c=1;
};

void foo(const data_type *);

#define GET_ADDRESS(object) ((object)->getAddress())

int main(int argc, char *argv[])
{
data_type temp_object;
temp_object.init_data_type();
foo(&temp_object);
}
void foo(const data_type *temp_object)
{
using namespace std;

if (((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a)
cout << "Test Passed";
//Error error: passing `const
//data_type' as `this' argument of `void* data_type::getAddress
//()' discards qualifiers
}

Look up 'const member function'.

-Mike
 
T

Thomas Matthews

Thanks,
read.
is difficult to
top-post, it
Please.

Append your replies to the end or intersperse.

Mahesh Tomar wrote:
[Re-arranged]
Mike Wahler said:
See below.

Dear Readers,
I am porting my existing C code to C++. In my existing code
there are numerous functions that has been defined with CONST
qualifier. For eg. foo(const DATA_TYPE *x); DATA_TYPE is some typedef
structure and offcourse x is a pointer to it. Needless to say my
intention for writing such functions in C was to protect the accident
write to x's content. So far so good. While porting to C++, I've mada
DATA_TYPE as class and I want to retain the sanity of existing C
function that has Const qualifier. However am having some trouble,
which is illustrated in the sample code below :

#include <iostream>
typedef struct _temp {
int a;
char b;
short int c;
}TEMP_STRUCT; // Define some temporary structure for illustration
purpose

class data_type
{
public :
void *address;
data_type(void);
~data_type();
void init_data_type();
void * getAddress() ;

void *getAddress() const;

};

data_type::data_type()
{
address = new TEMP_STRUCT;
}
inline void * data_type::getAddress()

inline void * data_type::getAddress() const

{
return((void *)address);
}
inline void data_type::init_data_type()
{
address->a=1;
address->b='a';
address->c=1;
};

void foo(const data_type *);

#define GET_ADDRESS(object) ((object)->getAddress())

int main(int argc, char *argv[])
{
data_type temp_object;
temp_object.init_data_type();
foo(&temp_object);
}
void foo(const data_type *temp_object)
{
using namespace std;

if (((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a)
cout << "Test Passed";
//Error error: passing `const
//data_type' as `this' argument of `void* data_type::getAddress
//()' discards qualifiers
}

Look up 'const member function'.

-Mike

Mike,
Thanks for your time. However, I too have mentioned the solution in
my original e-mail where I stated "if member function,get_address, is
defined as " void * getAddress() const", the compiler error goes away,
however, const qualifier inside foo also looses its meaning i.e. you
can write to the content of data type."
Putting a const qualifier at the end of function will make the error
go away, however, if I do something like this
void foo(const data_type *temp_object)
{
using namespace std;

// This statement below will modify the content of temp_object and
that is
// not the intention.
((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a = 2;
cout << ((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a;
}
If you see above, the intent of foo () function which was suppose to
protect any accidental write to the content of temp_object is lost. In
short I want to maintain the sanity of such functions (that am porting
to C++).
Any insight into this will be really appreciated.

Thanks,
Mahesh

Have a look at:
http://www.parashift.com/c++-faq-lite/const-correctness.html

See also section 18.11

Also, do yourself a favor and get rid of the macro.
const data_type *temp_object;
((TEMP_STRUCT *)(GET_ADDRESS(temp_object)))->a = 2;

translates to:
1. ((TEMP_STRUCT *) (temp_object->get_address()))->a = 2;
2. ((struct _temp *) (temp_object->get_address()))->a = 2;

The expression:
(temp_object->get_address())
returns a type of "void *", which you are casting to
a type of "struct _temp *".

As we look in the definition of class "data_type" above,
we find in the constructor, that "address" is
initialized as:
address = new _temp; /* simplified */

So, you have a casting circle:
1. Member address in class "data_type" is set to a new "_temp".
2. In function foo, the the address is fetched from
an instance of "data_type" and casted to a type "_temp".

Your program could be simplified by reducing the casts:
void foo (_temp * const const_temp_pointer)
{
if (const_temp_pointer->a)
{
cout << "Test Passed." << endl;
}
}

int main(void)
{
_temp temp_object;
foo(&temp_object);
}

or:
int main(void)
{
_temp * p_temp_object = new _temp;
foo(p_temp_object);
}


Did I miss something?
Are you trying to create some kind of smart pointer class?
{Smart pointers are also in the FAQ.}

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
O

Old Wolf

class data_type
{
public :
void *address;
data_type(void);
~data_type();
void init_data_type();
void * getAddress() ;
};
In C functions like foo() were called with "const TEMP_STRUCT *"
argument therefore compiler took care of any accident write to its
content. However in C++ this argument is changed to a class, which
fetches the address to TEMP_STRUCT, however, I still want the class to
return the address in such a way that the content of address can't be
modified inside the function. However, above sample code doesn't work
because foo is called with const qualifier, therefore complier
complains, if I try to access any of its member function. However if
get_address is defined as " void * getAddress() const", the compiler
error goes away, however, const qualifier inside foo also looses its
meaning i.e. you can write to the content of data type.

const void * getAddress() const;

(as well as your existing one). Then const objects will call this
one and return a const void *, and non-const objects will call
the existing one.
BTW using 'void *' is bad because of type safety issues, you
should consider using a template:

template<typename T>
class data_type
{
public:
T *address;
data_type(): address(new T) {}
~data_type() { delete address; }
void init_data_type();
T * getAddress() { return address; }
T const *getAddress() const { return address; }
};

Your init_data_type function would not have worked anyway
(you can't dereference a pointer to void). So:

data_type<TEMP_STRUCT>::init_data_type()
{
address->a=1;
address->b='a';
address->c=1;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top