Const Qualifier question

Discussion in 'C++' started by Mahesh Tomar, Sep 1, 2004.

  1. Mahesh Tomar

    Mahesh Tomar Guest

    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
     
    Mahesh Tomar, Sep 1, 2004
    #1
    1. Advertising

  2. Mahesh Tomar

    Mike Wahler Guest

    "Mahesh Tomar" <> wrote in message
    news:...

    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 Wahler, Sep 1, 2004
    #2
    1. Advertising

  3. Mahesh Tomar

    Mahesh Tomar Guest

    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" <> wrote in message news:<1JmZc.4672$w%>...
    > "Mahesh Tomar" <> wrote in message
    > news:...
    >
    > 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
     
    Mahesh Tomar, Sep 2, 2004
    #3
  4. Thanks,
    read.
    is difficult to
    top-post, it
    Please.

    Append your replies to the end or intersperse.

    Mahesh Tomar wrote:
    [Re-arranged]
    > "Mike Wahler" <> wrote in message news:<1JmZc.4672$w%>...
    >
    >>"Mahesh Tomar" <> wrote in message
    >>news:...
    >>
    >>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
     
    Thomas Matthews, Sep 2, 2004
    #4
  5. Mahesh Tomar

    Old Wolf Guest

    (Mahesh Tomar) wrote:

    > 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;
    }
     
    Old Wolf, Sep 2, 2004
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sergey Tolstov

    const qualifier and VC6.0

    Sergey Tolstov, Oct 7, 2003, in forum: C++
    Replies:
    8
    Views:
    490
    Howard
    Oct 7, 2003
  2. Patrick Guio

    const qualifier problem

    Patrick Guio, Nov 9, 2004, in forum: C++
    Replies:
    5
    Views:
    336
    Vyacheslav Kononenko
    Nov 9, 2004
  3. Zeng Dinghao
    Replies:
    3
    Views:
    493
    Andrey Tarasevich
    Nov 11, 2004
  4. Javier
    Replies:
    2
    Views:
    604
    James Kanze
    Sep 4, 2007
  5. paulo
    Replies:
    9
    Views:
    734
    James Kanze
    Mar 6, 2009
Loading...

Share This Page