C ++方法声明中最后一个“const”的含义?
const
在这些声明中的含义是什么? const
让我困惑。
class foobar { public: operator int () const; const char* foo() 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(); }
这将输出
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
方法可以更改它。 它主要用于内部计数器和东西。 解决scheme将是下面的代码。
#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
常量意味着该方法承诺不会改变任何类的成员。 即使对象本身被标记为const
,您也可以执行对象的如此标记的成员:
const foobar fb; fb.foo();
将是合法的。
请参阅C ++中“const”的用法和使用方法? 了解更多信息。
const
限定符意味着可以在foobar
任何值上调用方法。 当你考虑在一个const对象上调用一个非const方法的时候,会有所不同。 考虑如果你的foobar
types有以下额外的方法声明:
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);
这些常量意味着编译器将错误,如果方法“与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 }
阅读此以获取更多信息
布莱尔的回答是关键的。
但是请注意,有一个mutable
限定符可以被添加到类的数据成员。 如此标记的任何成员都可以在不违反const
约定的情况下在const
方法中进行修改。
如果你想要一个对象记住一个特定方法被调用的次数,而不影响该方法的“逻辑”常量,你可能想要使用它(例如)。
当你在方法签名中使用const
(就像你所说的: const char* foo() const;
),你告诉编译器这个指向的内存不能被这个方法改变(这里是foo
)。
C ++ 常量成员函数的含义 常识:基本中级编程给出了一个清晰的解释:
这个指针在类X的非const成员函数中的types是X * const。 也就是说,它是一个指向非常数X的常量指针(参见Const指针和指向Const的指针[7,21])。 因为这个引用的对象不是const的,所以它可以被修改。 这个在类X的const成员函数中的types是const X * const。 也就是说,它是一个指向常量X的常量指针。因为这个引用的对象是const,所以它不能被修改。 这是const和非const成员函数的区别。
所以在你的代码中:
class foobar { public: operator int () const; const char* foo() const; };
你可以这样想:
class foobar { public: operator int (foobar * const this) const; const char* foo(const foobar * const this) const; };