CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Feb 2004
    Location
    Texas, USA
    Posts
    1,206

    Question about CV-Qualifiers for class members

    Hello,

    I'm looking for the location in the C++03 standard that discusses the rules for const qualification of members when a class object is const-qualified. For example, if I have a class like this:

    Code:
    class Fubar
    {
      int* m_myInt;
      char*** m_myComplexPtr;
    };
    And I create a variable like this:

    Code:
    Fubar const foo;
    How are the members m_myInt and m_myComplexPtr const-qualified? For example, is it like this:

    Code:
    int const* const m_myInt;
    char const* const* const* const m_myComplexPtr;
    Or is it:

    Code:
    int* const m_myInt;
    char*** const m_myComplexPtr;
    I'm not really sure of the detailed language rules for this stuff. For pointers, you would think that technically the pointer would be made const, and not the data it points to, since the pointer is owned by the class (and thus must be guaranteed to be immutable), but the data being pointed to is not owned by the class, it is owned by the pointer. I guess constness is transitive this way?
    --MrDoomMaster
    --C++ Game Programmer


    Don't forget to rate me if I was helpful!

  2. #2
    Join Date
    Feb 2009
    Posts
    326

    Re: Question about CV-Qualifiers for class members

    Quote Originally Posted by MrDoomMaster View Post
    I'm not really sure of the detailed language rules for this stuff. For pointers, you would think that technically the pointer would be made const, and not the data it points to, since the pointer is owned by the class (and thus must be guaranteed to be immutable), but the data being pointed to is not owned by the class, it is owned by the pointer. I guess constness is transitive this way?
    That is not true, it doesn't work that way.

    When an object is declared as a const, the "this" pointer becomes the type "const Fubar* const"

    The first const means the contents or the members can't be modified. (The second const means that "this" pointer can't point to any other object, well every "this" pointer can't point to anything else, so even a normal non const object would have the "this" pointer of the type "Fubar* const")

    In your case it means that "m_myInt" and "m_myComplexPtr" can't be modified.

    The rest of it can all be modified. I have shown with your example below (code contains comments):

    Code:
    class Fubar
    {
        public:
            Fubar();
            void f1();
            void f2() const; //Promises to the compiler that it would not modify the contents of the object
                             //"this" pointer will always be of the type const Fubar* irrespective of whether the calling object is a const or not.
                
            int* m_myInt;
            char*** m_myComplexPtr;
    };
    
    int main()
    {
        Fubar const foo; //This works, bcz this const object is intialized by the default constructor defined
    
        /*  
        When you define an object as a const, then the "this" pointer becomes the type const Fubar*
        Meaning you can't modify the contents of the object
        Note - In this case all it would be concerned about is that you don't modify m_myInt and m_myComplexPtr
        You can modify anything other than that.
        */
    
        //foo.m_myInt = new int;              //Illegal, buz you are modifying the member of the class
        //foo.m_myComplexPtr = new char**;    //Illegal, bcuz you are modifying the member of the class
            
        //The rest of it is all legal
        *(foo.m_myInt) = 5;                //Legal
        *(foo.m_myComplexPtr) = new char*; //Legal
        **(foo.m_myComplexPtr) = new char; //Legal
        ***(foo.m_myComplexPtr) = 'a';     //Legal
    
        //Lets consider some member functions
        //foo.f1();     //Illegal, thought it doesn't modify the object contents, it doesn't promise the compiler it wouldn't modify the contents.
        foo.f2();       //Legal, as it makes the promise that it wouldn't modify the contents.
    
    
        return(0);
    }
    
    Fubar :: Fubar()
        : m_myInt(new int), m_myComplexPtr(new char**)
    {}
    
    void Fubar :: f1()
    {}
    
    void Fubar :: f2() const
    {}

    I know you didn't ask for the below, but thought I would state cuz this is related to constness (code contains comments):
    Code:
    int main()
    {
        const int * const * const * const v1 = new int**;
    
        /*  
        What each const means is explained below:
        
        First const (left most const) means that modifying ***v1 is illegal
        Second const means that modifying **v1 is illegal
        Third const means that modifying *v1 is illegal
        Fourth const means that modifying v1 is illegal
        
        */
    
        return(0);
    }
    Last edited by Muthuveerappan; September 1st, 2009 at 07:41 PM.

  3. #3
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Question about CV-Qualifiers for class members

    >> That is not true, it doesn't work that way.
    I *think* you misunderstood (see "[member]" below)

    >> you would think that technically the [member] pointer would be made const, and not the data it points to
    Correct. You can think of it as a "const" at the beginning of each member variable.

    >> When an object is declared as a const, the "this" pointer becomes the type "const Fubar* const"
    The last "const" shouldn't be there - but anyone reading your fine example will realize that

    gg

  4. #4
    Join Date
    Feb 2009
    Posts
    326

    Re: Question about CV-Qualifiers for class members

    Thanks Codeplug , I think i misunderstood MrDoomMaster's comments, am sorry about that.

    I have a small doubt (correct me if I am wrong), I thought the "this" pointer can't point to any other object .... rite ?

    I thought in "const Fubar* const", doesn't the 2nd const attribute to the fact that the "this" pointer can't point to anything else ?

    Code:
    class ClassA
    {
        void f1();    
    };
    
    int main()
    {   
       return(0);
    }
    
    void ClassA :: f1()
    {
        this = new ClassA; //Illegal, I am assuming "this" is of the type ClassA * const, correct me if am wrong, but at least seems to behave that way
    
    }

  5. #5
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Question about CV-Qualifiers for class members

    Ah, you're right. I was thinking of member pointers and not 'this'.

    gg

  6. #6
    Join Date
    Feb 2004
    Location
    Texas, USA
    Posts
    1,206

    Re: Question about CV-Qualifiers for class members

    Thanks for the info everyone. What about const member functions? I never try to modify the data being pointed to by the pointer, so I'm not really sure about this fundamental rule. If I call a const member function from a non-const class object and that const member function tries to modify the data being pointed to by either calling a non-const member function on that type or by modifying it directly (i.e., *m_myObj = 10; ), will the compiler accept that?
    --MrDoomMaster
    --C++ Game Programmer


    Don't forget to rate me if I was helpful!

  7. #7
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Question about CV-Qualifiers for class members

    Code:
    struct foo
    {
        int *p;
        void assign(int n) const {*p = n;}
    };//foo
    
    int main()
    {
        int n = 0;
        const foo f = {&n};
        f.assign(3);
        return 0;
    }//main
    The "int *p" member becomes "const int *p" - meaning p can't change, but what it points to still can.

    gg

  8. #8
    Join Date
    Feb 2004
    Location
    Texas, USA
    Posts
    1,206

    Re: Question about CV-Qualifiers for class members

    Quote Originally Posted by Codeplug View Post
    Code:
    struct foo
    {
        int *p;
        void assign(int n) const {*p = n;}
    };//foo
    
    int main()
    {
        int n = 0;
        const foo f = {&n};
        f.assign(3);
        return 0;
    }//main
    The "int *p" member becomes "const int *p" - meaning p can't change, but what it points to still can.

    gg
    If that's the case then I'm sure you meant "int* const p".

    You have all confirmed that how I originally thought this worked is indeed correct. However, I guess I'm a bit disappointed. I've always used the utmost const correctness in my code, so when I had a const member function I never attempted to modify the pointer value of pointer members OR the data they point to. It's just been a natural habit of mine. However, if I did something like this:

    Code:
    class Fubar
    {
      Obj* m_obj;
      void ChangeNothing() const { m_obj->NonConstMemberFunction(); }
    };
    I would expect the compiler to at least issue a warning, since we're mutating the state of Fubar as far as I'm concerned. I consider the object being pointed to as fundamentally part of the object's state, even though the compiler might not. In the example above, the const member function is treating m_obj as if it were defined like so:

    Code:
    Obj* const m_obj;
    When I really would like it to treat it like this:

    Code:
    Obj const* const m_obj;
    Maybe I'm being naive about this and not seeing the repercussions, but the latter seems like the way pointer members should be treated. Pointers should be transitively treated as const all the way down to their actual core type (Which in this case is 'Obj').
    Last edited by MrDoomMaster; September 2nd, 2009 at 09:52 AM.
    --MrDoomMaster
    --C++ Game Programmer


    Don't forget to rate me if I was helpful!

  9. #9
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Question about CV-Qualifiers for class members

    >> If that's the case then I'm sure you meant "int* const p".
    Yeah, I'm having a hard time.

    >> I guess I'm a bit disappointed
    You could create a reference to the object with increased cv-qualification:
    Code:
    Obj const * const &ref = m_obj;
    gg

  10. #10
    Join Date
    Feb 2009
    Posts
    326

    Re: Question about CV-Qualifiers for class members

    Codeplug, yeah you can have as you suggested:
    Code:
    Obj const * const &ref = m_obj;
    Just thought I must state that while the concept perfectly correct, there is a bug with gcc version 4.2.1 (Apple Inc. build 5646)

    Given below is a program to illustrate the bug, but however the concept is correct:

    Both (p1 and p2) are supposed to share the same location, but with gcc they don't share the same memory location, so thats a bug I suppose. I think it works on msvc:

    So when p1 is made to point to a different variable n2, p2 still points to the old variable n1.

    Code:
    #include <iostream>
    using std :: cout;
    using std :: endl;
    
    int main()
    {
         
        system("clear");
    
        int n1 = 5,
            n2 = 6;
    
        int *p1 = &n1;
        const int* const& p2 = p1; 
    
        cout << "*p1 = " << *p1 << "\t\tp1 = " << p1 << "\t&p1 = " << &p1 << endl
             << "*p2 = " << *p2 << "\t\tp2 = " << p2 << "\t&p2 = " << &p2 << endl << endl;
    
        p1 = &n2;
    
        cout << "*p1 = " << *p1 << "\t\tp1 = " << p1 << "\t&p1 = " << &p1 << endl
             << "*p2 = " << *p2 << "\t\tp2 = " << p2 << "\t&p2 = " << &p2 << endl << endl;
    
        return(0);
    }
    output:
    Code:
    *p1 = 5		p1 = 0x7fff5fbfe2bc	&p1 = 0x7fff5fbfe2b0
    *p2 = 5		p2 = 0x7fff5fbfe2bc	&p2 = 0x7fff5fbfe2a0
    
    *p1 = 6		p1 = 0x7fff5fbfe2b8	&p1 = 0x7fff5fbfe2b0
    *p2 = 5		p2 = 0x7fff5fbfe2bc	&p2 = 0x7fff5fbfe2a0
    You could also refer the following post (page2) for the answer:
    http://www.codeguru.com/forum/showthread.php?t=479104
    Last edited by Muthuveerappan; September 2nd, 2009 at 12:56 PM.

  11. #11
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Question about CV-Qualifiers for class members

    Quote Originally Posted by Muthuveerappan View Post
    I think it works on msvc
    It does.

    Code:
    *p1 = 5         p1 = 0012FF60   &p1 = 0012FF48
    *p2 = 5         p2 = 0012FF60   &p2 = 0012FF48
    
    *p1 = 6         p1 = 0012FF54   &p1 = 0012FF48
    *p2 = 6         p2 = 0012FF54   &p2 = 0012FF48
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  12. #12
    Join Date
    Feb 2009
    Posts
    326

    Re: Question about CV-Qualifiers for class members

    Thanks John for confirming that.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured