Dealing with const

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Alex

    #1

    Dealing with const

    Hi. I'll try my problem with this example:

    class C {
    protected:
    virtual int* getProtected(in t index)=0;
    public:
    const int* get(int index) const
    { return (const int*) getProtected(in dex); }

    virtual void set(int index, int value)
    { *getProtected(i ndex) = value; }
    ...
    };

    class D : public C {
    protected:
    int* getProtected(in t index) { ... }
    };


    I need a way to set a value and get a const pointer to that thing. I
    want the base class to provide a standard way for set, which is just
    copy the value. My approach is to make it easy: the child classes only
    would need to implement getProtected and get() and set() will work ok.
    If that class needs to do some extra processing when set() is called,
    it can implement it, but otherwise it will work ok. getProtected is
    protected to prevent to get a non-const pointer outside the class.

    I don't know if you can understand me. Anyway, my problem is that that
    doesn't work, because getProtected is a const member function and get()
    is const.

    Can you help me?

    Thanks!!

  • Luke Meyers

    #2
    Re: Dealing with const

    One thing first -- there is an important difference between a "const
    pointer" (T * const) and a "pointer to constant" (const T *, T const
    *). It's a bit confusing to refer to the latter as the former. The
    linguistic awkwardness of the latter is probably the lesser evil.

    Anyway, on to your question... your problem arises from an incongruous
    policy with regard to state modification. A const member function
    promises not to modify the host object's state, either directly
    (assigning to a member variable) or indirectly (calling a non-const
    member function). If it is your policy to allow getProtected() to
    modify that state, then it is a semantic error to call it from get(),
    because as a const member function, get() promises not to modify that
    state.

    I wonder whether you're confusing the "const" modifier for variables
    with the "const" modifier for member functions. Since it is an
    interface sin to allow a member function with "get" in its name modify
    object state without a darn good reason, I'd just make both methods
    const and be done with it.

    I would also avoid using C-style casts. If you must cast, use
    const_cast, static_cast, or dynamic_cast. In this case, you don't need
    to cast at all because C++ can append the "const" modifier without a
    problem.

    A more interesting way to accomplish your aim here might be to provide
    the desired customization behavior as a policy given as a template
    parameter. Just a thought.

    Luke

    Comment

    • Alex

      #3
      Re: Dealing with const

      The problem is that I want to use getProtected sometimes to modify the
      value whose pointer is returned (set) and sometimes not (get).

      I think it is the same problema as in this example:


      class MyVector {
      protected:
      int& get(int i) {.... A LONG AND HARD PROCESSING ... }
      public:
      int& operator[](int i) { return get(i); }
      const int& operator[](int i) const { return get(i); } // I
      don't want to write twice get() code

      };

      Do you understad me now? I want to access a pointer in a const way when
      needed and y a non-const way some times. I don't want my base classess
      to redefine both methods, as I don't want in this example to write the
      get() code twice.



      }

      Comment

      • Bob Hairgrove

        #4
        Re: Dealing with const

        On 26 Dec 2005 02:11:58 -0800, "Alex" <acamposr@gmail .com> wrote:
        [color=blue]
        >The problem is that I want to use getProtected sometimes to modify the
        >value whose pointer is returned (set) and sometimes not (get).
        >
        >I think it is the same problema as in this example:
        >
        >
        >class MyVector {
        > protected:
        > int& get(int i) {.... A LONG AND HARD PROCESSING ... }
        > public:
        > int& operator[](int i) { return get(i); }
        > const int& operator[](int i) const { return get(i); } // I
        >don't want to write twice get() code
        >
        >};
        >
        >Do you understad me now? I want to access a pointer in a const way when
        >needed and y a non-const way some times. I don't want my base classess
        >to redefine both methods, as I don't want in this example to write the
        >get() code twice.[/color]

        For the const get() function, I would return the int by value, not by
        reference. But the root of the problem is the const'ness of the object
        itself. What are the circumstances where MyVector needs to be const?
        Can you do without the const?

        Maybe you could delegate the work done by get() into smaller
        functions, then isolate the ones that get in the way of using const. A
        reference is usually only returned from a function if there is a
        member object available. That should involve zero processing, and in
        fact such functions are usually inlined.

        --
        Bob Hairgrove
        NoSpamPlease@Ho me.com

        Comment

        • Alex

          #5
          Re: Dealing with const

          "What are the circumstances where MyVector needs to be const?
          Can you do without the const? "


          void f(const int& x);
          void g(int& x);

          ....
          MyVector v;
          f(v[0]); // const
          g(v[0]); // not const
          ....

          But MyVector is just an example. I need to return a const pointer and a
          non-const pointer. And I don't want the subclasses to redefine both,
          but just one, as I explain in the first post.

          Comment

          • BobR

            #6
            Re: Dealing with const


            Alex wrote in message
            <1135622352.873 654.270580@g44g 2000cwa.googleg roups.com>...[color=blue]
            >But MyVector is just an example. I need to return a const pointer and a
            >non-const pointer. And I don't want the subclasses to redefine both,
            >but just one, as I explain in the first post.[/color]

            You can assign a non-const to a const, but, not a const to a non-const.

            [ RW == Read-Write. RO == Read-Only ]

            int o(0); // RW
            int const oConst = 1; // must initialize a constant // RO
            int *p = &o; // int is RW, pointer is RW
            int const *pConst = &oConst; // int is RO, pointer is RW

            pConst = p; // ok
            pConst = pConst; // ok
            p = p; // ok
            // p = pConst; // won't compile (without a const_cast<>(). Think first!!)

            // p is pointing to memory that can be *read* or written to.
            *p = 43; // should be no problem. [ o == 43 ]

            pConst = p; // should not cause a problem. the int *can* be read.
            // *pConst = 43; // should cause a problem. "assignment of read-only
            location"
            // The 'int' is constant(RO) thru pointer, not the
            pointer to it.

            int * const pcConst = &o; // const pointer to an RW int.
            // pcConst=p; // should cause a problem. the pointer is const.
            // assignment of read-only variable `pcConst'
            *pcConst = 43; // should not cause a problem. [ o == 43 ]

            // int const * const pccConst( &oConst ); // ok
            int const * const pccConst( &o ); // 'o' is RW
            // pccConst = p; // nope. the pointer is const.
            // *pccConst = 43; // nope. What it points to is RO thru pointer.


            If you are the slightest bit light-headed on pointers, you should go get Mr.
            Steinbach's tutorial:

            -----Original Message-----
            From: Alf P. Steinbach
            Newsgroups: alt.comp.lang.l earn.c-c++,comp.lang.c ++,no.it.progra mmering.c++
            Date: Thursday, December 08, 2005 12:04 AM
            Subject: Finally, a release candidate of the "Pointers" document
            (introduction to pointers)




            --
            Bob R
            POVrookie


            Comment

            • Alex

              #7
              Re: Dealing with const

              I know all that about pointers and I know perfectly why my example
              doesn't work (I haven't implemented it because I know what would
              happen). I am asking for a design tip to do the same I want to do in my
              example.

              Comment

              • Jonathan Mcdougall

                #8
                Re: Dealing with const

                Alex wrote:[color=blue]
                > Hi. I'll try my problem with this example:
                >
                > class C {
                > protected:
                > virtual int* getProtected(in t index)=0;
                > public:
                > const int* get(int index) const
                > { return (const int*) getProtected(in dex); }
                >
                > virtual void set(int index, int value)
                > { *getProtected(i ndex) = value; }
                > ...
                > };
                >
                > class D : public C {
                > protected:
                > int* getProtected(in t index) { ... }
                > };
                >
                >
                > I need a way to set a value and get a const pointer to that thing. I
                > want the base class to provide a standard way for set, which is just
                > copy the value. My approach is to make it easy: the child classes only
                > would need to implement getProtected and get() and set() will work ok.
                > If that class needs to do some extra processing when set() is called,
                > it can implement it, but otherwise it will work ok. getProtected is
                > protected to prevent to get a non-const pointer outside the class.
                >
                > I don't know if you can understand me. Anyway, my problem is that that
                > doesn't work, because getProtected is a const member function and get()
                > is const.[/color]

                Well in this case you're lying: getProtected() is non-const and you try
                to call it from a const member function. If you were able to do that,
                get() wouldn't be a const member function anymore. Shame on you.

                There is no easy way to do that, except with const_cast, which you
                should try to avoid. You could have getProtected() return by value
                instead.

                If getProtected() returns an address of a member object, forget it.
                You'll have to duplicate the function. Isn't it possible to split
                getProtected() into getCommon() for this to be easier?


                Jonathan

                Comment

                • Luke Meyers

                  #9
                  Re: Dealing with const

                  Well, the only way I see to do it is to cast away the const at some
                  point. You can do it inside your setter, or inside getProtected prior
                  to returning it. That said, if it were me, I'd explore dozens of other
                  solutions before resorting to casting away const.

                  I did recently come up with a case where casting away const was exactly
                  the right thing to do. I had a vector< boost::shared_p tr<Foo> > as
                  member data to an object which provides a removeFooFromLi st method that
                  takes a boost::shared_p tr<Foo>. Since I'm not going to modify the Foo,
                  from an interface standpoint I should take a boost::shared_p tr<const
                  Foo>. But the vector doesn't recognize that as an is-a for its
                  contained type, so I had to cast off the const from inside the pointer
                  in order to do the removal. So, it does legitimately come up, but...
                  still leaves a nasty taste in one's mouth.

                  I'm still trying to come up with some funky solution for your problem
                  involving template magic, but no flash of inspiration so far.

                  Luke

                  Comment

                  • Niklas Norrthon

                    #10
                    Re: Dealing with const

                    "Alex" <acamposr@gmail .com> writes:
                    [color=blue]
                    > I know all that about pointers[/color]

                    All what?
                    [color=blue]
                    > and I know perfectly why my example doesn't work[/color]

                    What example?
                    [color=blue]
                    > (I haven't implemented it because I know what would happen).
                    > I am asking for a design tip to do the same I want to do in my
                    > example.[/color]

                    To do what? I don't see any example. Please provide some context
                    when you post.

                    /Niklas Norrthon

                    Comment

                    Working...