'const'在类的函数声明中的含义是什么?

689 c++ const declaration c++-faq

const这些声明中的含义是什么?该const混淆了我.

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};
Run Code Online (Sandbox Code Playgroud)

Mat*_*son 897

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();
}
Run Code Online (Sandbox Code Playgroud)

这将输出

Foo
Foo const
Run Code Online (Sandbox Code Playgroud)

在非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;
    }
Run Code Online (Sandbox Code Playgroud)

这不完全正确,因为您可以将成员标记为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 << "Foo has been invoked " << ccc.GetInvocations() << " times" << endl;
}
Run Code Online (Sandbox Code Playgroud)

哪个会输出

Foo
Foo const
Foo has been invoked 2 times
Run Code Online (Sandbox Code Playgroud)

  • 如果我只创建一个 const 方法但没有普通方法,然后使用非常量对象调用该方法,我的代码通常运行良好。这是错误的、有害的还是什么? (6认同)
  • @KhiemGOM 这完全没问题,对于只读成员来说是非常正常的模式。 (4认同)

Bla*_*rad 180

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

const foobar fb;
fb.foo();
Run Code Online (Sandbox Code Playgroud)

是合法的.

在C++中查看"const"的用法和用途是什么?欲获得更多信息.


Jar*_*Par 46

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

class foobar {
  ...
  const char* bar();
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

foobar& fbNonConst = const_cast<foobar&>(fb1);
Run Code Online (Sandbox Code Playgroud)

  • 我认为答案是关于其他const方法而不是const对象. (2认同)

Myk*_*yev 23

这些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_;
};
Run Code Online (Sandbox Code Playgroud)

考试

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
}
Run Code Online (Sandbox Code Playgroud)

阅读本文以获取更多信息

  • 关于没有提到 [mutable](http://en.cppreference.com/w/cpp/keyword/mutable) 的 `const` 成员函数的问题充其量是不完整的。 (2认同)

Aln*_*tak 12

布莱尔的回答很明显.

但请注意,有一个mutable限定符可以添加到类的数据成员中.如此标记的任何成员可以在const不违反const合同的情况下进行修改.

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


Nan*_*iao 8

一个const成员函数的意义C++常识:基本中级设计给出了明确的解释:

类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;
};
Run Code Online (Sandbox Code Playgroud)

你可以这样认为:

class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};
Run Code Online (Sandbox Code Playgroud)


cod*_*101 7

我想补充以下几点。

你也可以把 它变成一个const &const &&

所以,

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
}

Run Code Online (Sandbox Code Playgroud)

随意改进答案。我不是专家


Mat*_*ter 6

当您const在方法签名中使用时(如您所说的那样const char* foo() const;),您告诉编译器this该方法无法更改指向的内存(foo在此处).


小智 6

这里 const 意味着在该函数中任何变量的值都不能改变

class Test{
private:
    int a;
public:
    void test()const{
        a = 10;
    }
};
Run Code Online (Sandbox Code Playgroud)

就像这个例子一样,如果您尝试更改测试函数中变量的值,您将收到错误。