Meaning of 'const' last in a function declaration of a class?

后端 未结 10 2089
无人共我
无人共我 2020-11-21 06:37

What is the meaning of const in declarations like these? The const confuses me.

class foobar
{
  public:
     operator int () const         


        
相关标签:
10条回答
  • 2020-11-21 07:13

    The const means that the method promises not to alter any members of the class. You'd be able to execute the object's members that are so marked, even if the object itself were marked const:

    const foobar fb;
    fb.foo();
    

    would be legal.

    See How many and which are the uses of “const” in C++? for more information.

    0 讨论(0)
  • 2020-11-21 07:13

    I would like to add the following point.

    You can also make it a const & and const &&

    So,

    struct s{
        void val1() const {
         // *this is const here. Hence this function cannot modify any member of *this
        }
        void val2() const & {
        // *this is const& here
        }
        void val3() const && {
        // The object calling this function should be const rvalue only.
        }
        void val4() && {
        // The object calling this function should be rvalue reference only.
        }
    
    };
    
    int main(){
      s a;
      a.val1(); //okay
      a.val2(); //okay
      // a.val3() not okay, a is not rvalue will be okay if called like
      std::move(a).val3(); // okay, move makes it a rvalue
    }
    
    

    Feel free to improve the answer. I am no expert

    0 讨论(0)
  • 2020-11-21 07:16

    https://isocpp.org/wiki/faq/const-correctness#const-member-fns

    What is a "const member function"?

    A member function that inspects (rather than mutates) its object.

    A const member function is indicated by a const suffix just after the member function’s parameter list. Member functions with a const suffix are called “const member functions” or “inspectors.” Member functions without a const suffix are called “non-const member functions” or “mutators.”

    class Fred {
    public:
      void inspect() const;   // This member promises NOT to change *this
      void mutate();          // This member function might change *this
    };
    void userCode(Fred& changeable, const Fred& unchangeable)
    {
      changeable.inspect();   // Okay: doesn't change a changeable object
      changeable.mutate();    // Okay: changes a changeable object
      unchangeable.inspect(); // Okay: doesn't change an unchangeable object
      unchangeable.mutate();  // ERROR: attempt to change unchangeable object
    }
    

    The attempt to call unchangeable.mutate() is an error caught at compile time. There is no runtime space or speed penalty for const, and you don’t need to write test-cases to check it at runtime.

    The trailing const on inspect() member function should be used to mean the method won’t change the object’s abstract (client-visible) state. That is slightly different from saying the method won’t change the “raw bits” of the object’s struct. C++ compilers aren’t allowed to take the “bitwise” interpretation unless they can solve the aliasing problem, which normally can’t be solved (i.e., a non-const alias could exist which could modify the state of the object). Another (important) insight from this aliasing issue: pointing at an object with a pointer-to-const doesn’t guarantee that the object won’t change; it merely promises that the object won’t change via that pointer.

    0 讨论(0)
  • 2020-11-21 07:17

    These const mean that compiler will Error if the method 'with const' changes internal data.

    class A
    {
    public:
        A():member_()
        {
        }
    
        int hashGetter() const
        {
            state_ = 1;
            return member_;
        }
        int goodGetter() const
        {
            return member_;
        }
        int getter() const
        {
            //member_ = 2; // error
            return member_;
        }
        int badGetter()
        {
            return member_;
        }
    private:
        mutable int state_;
        int member_;
    };
    

    The test

    int main()
    {
        const A a1;
        a1.badGetter(); // doesn't work
        a1.goodGetter(); // works
        a1.hashGetter(); // works
    
        A a2;
        a2.badGetter(); // works
        a2.goodGetter(); // works
        a2.hashGetter(); // works
    }
    

    Read this for more information

    0 讨论(0)
  • 2020-11-21 07:19

    When you add the const keyword to a method the this pointer will essentially become a pointer to const object, and you cannot therefore change any member data. (Unless you use mutable, more on that later).

    The const keyword is part of the functions signature which means that you can implement two similar methods, one which is called when the object is const, and one that isn't.

    #include <iostream>
    
    class MyClass
    {
    private:
        int counter;
    public:
        void Foo()
        { 
            std::cout << "Foo" << std::endl;    
        }
    
        void Foo() const
        {
            std::cout << "Foo const" << std::endl;
        }
    
    };
    
    int main()
    {
        MyClass cc;
        const MyClass& ccc = cc;
        cc.Foo();
        ccc.Foo();
    }
    

    This will output

    Foo
    Foo const
    

    In the non-const method you can change the instance members, which you cannot do in the const version. If you change the method declaration in the above example to the code below you will get some errors.

        void Foo()
        {
            counter++; //this works
            std::cout << "Foo" << std::endl;    
        }
    
        void Foo() const
        {
            counter++; //this will not compile
            std::cout << "Foo const" << std::endl;
        }
    

    This is not completely true, because you can mark a member as mutable and a const method can then change it. It's mostly used for internal counters and stuff. The solution for that would be the below code.

    #include <iostream>
    
    class MyClass
    {
    private:
        mutable int counter;
    public:
    
        MyClass() : counter(0) {}
    
        void Foo()
        {
            counter++;
            std::cout << "Foo" << std::endl;    
        }
    
        void Foo() const
        {
            counter++;    // This works because counter is `mutable`
            std::cout << "Foo const" << std::endl;
        }
    
        int GetInvocations() const
        {
            return counter;
        }
    };
    
    int main(void)
    {
        MyClass cc;
        const MyClass& ccc = cc;
        cc.Foo();
        ccc.Foo();
        std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
    }
    

    which would output

    Foo
    Foo const
    Foo has been invoked 2 times
    
    0 讨论(0)
  • 2020-11-21 07:19

    The const qualifier means that the methods can be called on any value of foobar. The difference comes when you consider calling a non-const method on a const object. Consider if your foobar type had the following extra method declaration:

    class foobar {
      ...
      const char* bar();
    }
    

    The method bar() is non-const and can only be accessed from non-const values.

    void func1(const foobar& fb1, foobar& fb2) {
      const char* v1 = fb1.bar();  // won't compile
      const char* v2 = fb2.bar();  // works
    }
    

    The idea behind const though is to mark methods which will not alter the internal state of the class. This is a powerful concept but is not actually enforceable in C++. It's more of a promise than a guarantee. And one that is often broken and easily broken.

    foobar& fbNonConst = const_cast<foobar&>(fb1);
    
    0 讨论(0)
提交回复
热议问题