关于c ++:’const’在类的函数声明中的含义是什么?

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

在这样的声明中,EDOCX1[0]的含义是什么?江户记1〔0〕把我搞糊涂了。

1
2
3
4
5
6
class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

在方法中添加const关键字时,this指针实质上将成为指向const对象的指针,因此不能更改任何成员数据。(除非你使用mutable,以后会更多)。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#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();
}

这将输出

1
2
Foo
Foo const

在非常量方法中,您可以更改实例成员,在const版本中不能这样做。如果将上述示例中的方法声明更改为下面的代码,则会出现一些错误。

1
2
3
4
5
6
7
8
9
10
11
    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方法可以更改它。它主要用于内部柜台和物品。解决方法是下面的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#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;
}

哪个会输出

1
2
3
Foo
Foo const
The MyClass instance has been invoked 2 times

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

1
2
const foobar fb;
fb.foo();

是合法的。

看看C++中"const"的用法和用法是多少?更多信息。


const限定符表示可以对foobar的任何值调用方法。当您考虑对一个常量对象调用一个非常量方法时,就会有不同。考虑您的foobar类型是否具有以下额外的方法声明:

1
2
3
4
class foobar {
  ...
  const char* bar();
}

方法bar()为非常量,只能从非常量值访问。

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

不过,const背后的思想是标记不会改变类内部状态的方法。这是一个强大的概念,但实际上不能在C++中强制执行。与其说是保证,不如说是承诺。以及一个经常破损且容易破损的。

1
foobar& fbNonConst = const_cast<foobar&>(fb1);


这些常量意味着如果"with const"方法更改内部数据,编译器将出错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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_;
};

测试

1
2
3
4
5
6
7
8
9
10
11
12
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
}

阅读此了解更多信息


布莱尔的回答是肯定的。

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

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


C++常用知识中一个const成员函数的含义:必要的中间程序给出了一个清晰的解释:

The type of the this pointer in a non-const member function of a class
X is X * const. That is, it’s a constant pointer to a non-constant X
(see Const Pointers and Pointers to Const [7, 21]). Because the object
to which this refers is not const, it can be modified. The type of
this in a const member function of a class X is const X * const. That
is, it’s a constant pointer to a constant X. Because the object to
which this refers is const, it cannot be modified. That’s the
difference between const and non-const member functions.

所以在你的代码中:

1
2
3
4
5
6
class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

你可以这样想:

1
2
3
4
5
6
class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};


当你在方法签名中使用const(如你所说的:const char* foo() const;)时,你告诉编译器,this所指的内存不能用这个方法改变(这里是foo)。


我想增加以下几点。

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

所以,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
}

请随时改进答案。我不是专家