首页 文章

'const' last在类的函数声明中的含义?

提问于
浏览
617

const 在这些声明中的含义是什么? const 让我困惑 .

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

7 回答

  • 20

    C++ Common Knowledge: Essential Intermediate Programming中Const成员函数的含义给出了清楚的解释:

    类X的非const成员函数中this指针的类型是X * const . 也就是说,它是一个指向非常数X的常量指针(参见Const Pointers和Pointers to Const [7,21]) . 因为它引用的对象不是const,所以可以修改它 . 类X的const成员函数中的类型是const X * const . 也就是说,它是一个指向常量X的常量指针 . 因为它引用的对象是const,所以它不能被修改 . 这是const和非const成员函数之间的区别 .

    所以在你的代码中:

    class foobar
    {
      public:
         operator int () const;
         const char* foo() const;
    };
    

    你可以这样认为:

    class foobar
    {
      public:
         operator int (const foobar * const this) const;
         const char* foo(const foobar * const this) const;
    };
    
  • 824

    const 关键字添加到方法时, this 指针实际上将成为指向 const 对象的指针,因此您无法更改任何成员数据 . (除非您使用 mutable ,稍后会详细介绍) .

    const 关键字是函数签名的一部分,这意味着您可以实现两个类似的方法,一个在对象是 const 时调用,另一个不是 .

    #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();
    }
    

    这将输出

    Foo
    Foo const
    

    在非const方法中,您可以更改实例成员,而这些成员在 const 版本中无法执行 . 如果您将上面示例中的方法声明更改为以下代码,则会出现一些错误 .

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

    这不完全正确,因为您可以将成员标记为 mutable ,然后 const 方法可以更改它 . 它主要用于内部计数器和东西 . 解决方案就是下面的代码 .

    #include <iostream>
    
    class MyClass
    {
    private:
        mutable int counter;
    public:
    
        MyClass() : counter(0) {}
    
        void Foo()
        {
            counter++;
            std::cout << "Foo" << std::endl;    
        }
    
        void Foo() const
        {
            counter++;
            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 << "The MyClass instance has been invoked " << ccc.GetInvocations() << " times" << endl;
    }
    

    哪个会输出

    Foo
    Foo const
    The MyClass instance has been invoked 2 times
    
  • 6

    const意味着该方法承诺不会改变该类的任何成员 . 即使对象本身已标记为 const ,您_111781_的成员也会如此标记:

    const foobar fb;
    fb.foo();
    

    是合法的 .

    有关更多信息,请参见How many and which are the uses of “const” in C++? .

  • 172

    const 限定符意味着可以在 foobar 的任何值上调用这些方法 . 当您考虑在const对象上调用非const方法时会出现差异 . 考虑您的 foobar 类型是否具有以下额外方法声明:

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

    方法 bar() 是非const的,只能从非const值访问 .

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

    const 背后的想法是标记不会改变类的内部状态的方法 . 这是一个强大的概念,但在C中实际上并不强制执行 . 这更像是承诺而非保证 . 而且经常被打破并容易被打破的人 .

    foobar& fbNonConst = const_cast<foobar&>(fb1);
    
  • 41

    这些const表示如果方法'with const'改变内部数据,编译器将出错 .

    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_;
    };
    

    考试

    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
    }
    

    有关更多信息,请阅读this

  • 4

    布莱尔的回答是正确的 .

    但请注意,有一个 mutable 限定符可以添加到类的数据成员中 . 如此标记的任何成员都可以在 const 方法中进行修改,而不会违反 const Contract .

    如果希望对象记住调用特定方法的次数,而不影响该方法的“逻辑”常量,则可能需要使用此(例如) .

  • 9

    当您在方法签名中使用 const 时(就像您所说的: const char* foo() const; ),您告诉编译器 this 指向的内存不能通过此方法更改(这里是 foo ) .

相关问题