在类的函数声明中“const”最后的含义?

在这样的声明中const是什么意思?const让我困惑。

class foobar{public:operator int () const;const char* foo() const;};
318794 次浏览

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

const foobar fb;fb.foo();

将是合法的。

有关更多信息,请参阅C++中“const”的用法有多少?

这些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; // errorreturn member_;}int badGetter(){return member_;}private:mutable int state_;int member_;};

该测试

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

阅读这个了解更多信息

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 compileconst char* v2 = fb2.bar();  // works}

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

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

布莱尔的回答是对的。

但是请注意,有一个mutable限定符可以添加到类的数据成员中。任何标记为可以的成员都可以在const方法中修改,而不会违反const契约。

如果您希望对象记住特定方法被调用的次数,同时不影响该方法的“逻辑”一致性,您可能希望使用它(例如)。

当您将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();}

这将输出

FooFoo const

在非const方法中,您可以更改实例成员,这在const版本中是无法做到的。如果您将上面示例中的方法声明更改为下面的代码,您将收到一些错误。

    void Foo(){counter++; //this worksstd::cout << "Foo" << std::endl;}
void Foo() const{counter++; //this will not compilestd::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++;    // 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;}

这将输出

FooFoo constFoo has been invoked 2 times

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

C++常识:基本中级编程中的常量成员函数的含义给出了明确的解释:

类的非const成员函数中this指针的类型X是X*const。也就是说,它是一个指向非常量X的常量指针(请参阅Const指针和Const指针[7,21])。因为对象this所指的不是const,它可以被修改。的类型this在类X的const成员函数中是const X*const。那是,它是指向常量X的常量指针。因为对象this引用的是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;};

我想补充以下一点。

您还可以制作#0和#1

所以,

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(); //okaya.val2(); //okay// a.val3() not okay, a is not rvalue will be okay if called likestd::move(a).val3(); // okay, move makes it a rvalue}

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

与函数声明一起使用的const关键字指定它是const成员函数,它将无法改变对象的数据成员。

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

什么是“const成员函数”?

检查(而不是改变)其对象的成员函数。

const成员函数在成员函数的参数列表后面用const后缀表示。带有const后缀的成员函数称为“const成员函数”或“检查器”。没有const后缀的成员函数称为“非const成员函数”或“修改器”。

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

尝试调用unchangeable.mutate()是在编译时捕获的错误。const没有运行时空间或速度损失,您不需要编写测试用例来在运行时检查它。

第一个成员函数的尾随const应该用来表示该方法不会改变对象的抽象(客户端可见)状态。这与说该方法不会改变对象结构的“原始位”略有不同。C++编译器不允许采取“按位”解释,除非他们能解决通常无法解决的混淆现象问题(即可能存在可以修改对象状态的非const别名)。从这个混淆现象中的另一个(重要)见解:用const指针指向一个对象并不能保证该对象不会改变;它只是承诺该对象不会改变通过那个指针

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

class Test{private:int a;public:void test()const{a = 10;}};

就像这个例子,如果你试图改变测试函数中变量的值,你会得到一个错误。

const对象中,只能调用const方法。这种方法中的所有字段都被视为const字段。最后一个问题有奇怪的效果:

  • 指针变为const指针int* const,与指向constconst int*的指针不同。因此,您可以更改指针指向的对象,但不能使指针指向另一个对象。
  • 引用应该成为一个const引用,但它总是一个const引用:您不能将其重新初始化到另一个对象。但您可以再次更改引用引用的对象。