Answers:
当您将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++; // 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;
}
将输出
Foo
Foo const
Foo has been invoked 2 times
const表示该方法保证不会更改该类的任何成员。即使对象本身已被标记,您也可以执行已标记的对象的成员const
:
const foobar fb;
fb.foo();
是合法的。
请参见C ++中“ const”的用途是什么?欲获得更多信息。
在const
预选赛的手段,该方法可以在任何值调用foobar
。当您考虑在const对象上调用非const方法时,会出现区别。考虑您的foobar
类型是否具有以下额外的方法声明:
class foobar {
...
const char* bar();
}
该方法bar()
是非常量的,只能从非常量值访问。
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);
const
尽管,其背后的想法是标记不会改变类内部状态的方法”。那才是我真正想要的。
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; // 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
}
阅读此以获得更多信息
const
没有提及可变的成员函数问题充其量是不完整的。
一个const成员函数的意义在C ++常识:基本中级设计给出了明确的解释:
X类的非常量成员函数中的this指针的类型为X * const。也就是说,它是指向非常量X的常量指针(请参见常量指针和指向常量的指针[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;
};
this
不是const
。无法修改的原因是它是prvalue。
我想补充以下几点。
您也可以 成为一个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
}
随时改善答案。我不是专家
*this
即使成员函数经过rvalue-ref限定并在rvalue上调用,它始终是一个左值。实例。
与函数声明一起使用的const关键字指定它是const成员函数,它将无法更改对象的数据成员。
https://isocpp.org/wiki/faq/const-correctness#const-member-fns
什么是“
const
成员函数”?检查(而不是变异)其对象的成员函数。
一个
const
成员函数由表示const
后缀只是成员函数的参数列表之后。带const
后缀的成员函数称为“常量成员函数”或“检查器”。没有const
后缀的成员函数称为“非常量成员函数”或“变量”。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 }
尝试调用
unchangeable.mutate()
是在编译时捕获的错误。没有的运行时空间或速度损失const
,您无需编写测试用例即可在运行时进行检查。尾部
const
上inspect()
成员函数应用于表示该方法不会改变该对象的抽象(客户端可见的)的状态。这与说该方法不会更改对象结构的“原始位”略有不同。除非C ++编译器可以解决通常无法解决的别名问题,否则C ++编译器不允许采用“按位”解释(即,可能存在可以修改对象状态的非const别名)。这个别名问题的另一个(重要的)见解:用指向const的指针指向一个对象并不能保证该对象不会改变。它只是保证对象不会通过该指针改变。