当通过具有CV资格的对该类的引用来访问它们时,该类中的函数可能会过载。这是最常用的过载const,但可用于过载volatile和const volatile,太。这是因为所有非静态成员函数都将其this用作隐藏参数,cv限定词将应用于该隐藏参数。这是最常用于重载的方法const,但也可以用于volatile和const volatile。
这是必需的,因为只有在至少具有与调用它的实例相同的cv资格的情况下,才可以调用该成员函数。非const实例既可以调用成员也可以调用const非const成员,而const实例只能调用const成员。这允许函数根据调用实例的cv-qualifiers具有不同的行为,并允许程序员qualifier(s)通过不提供带有该函数的版本来禁止不需要的cv-的函数qualifier(s)。
具有某些基本print方法的类可能会const像这样重载:
#include <iostream> class Integer { public: Integer(int i_): i{i_}{} void print() { std::cout << "int: " << i << std::endl; } void print() const { std::cout << "const int: " << i << std::endl; } protected: int i; }; int main() { Integer i{5}; const Integer &ic = i; i.print(); // prints "int: 5" ic.print(); // prints "const int: 5" }
这是const正确性的关键原则:通过将成员函数标记为const,可以在const实例上调用它们,这又允许函数在const不需要修改实例的情况下将其作为指针/引用。这允许代码通过将未修改的参数作为const和没有cv限定词的修改后的参数来指定是否修改状态,从而使代码更安全,更易读。
class ConstCorrect { public: void good_func() const { std::cout << "我不在乎实例是否为const。" << std::endl; } void bad_func() { std::cout << "I can only be called on non-const, non-volatile instances." << std::endl; } }; void i_change_no_state(const ConstCorrect& cc) { std::cout << "I can take either a const or a non-const ConstCorrect." << std::endl; cc.good_func(); //好。可以从const或非const实例中调用。 cc.bad_func(); //错误。只能从非const实例调用。 } void const_incorrect_func(ConstCorrect& cc) { cc.good_func(); //好。可以从const或非const实例中调用。 cc.bad_func(); //好。只能从非const实例调用。 }
这种方法的常见用法是将存取const器声明为,将变体声明为non- const。
在const成员函数中不能修改任何类成员。如果确实需要修改某些成员,例如锁定a std::mutex,则可以将其声明为mutable:
class Integer { public: Integer(int i_): i{i_}{} int get() const { std::lock_guard<std::mutex> lock{mut}; return i; } void set(int i_) { std::lock_guard<std::mutex> lock{mut}; i = i_; } protected: int i; mutable std::mutex mut; };