成員函式 cv-qualifier 過載
當通過對該類的 cv 限定引用訪問類中的函式時,它們可以過載; 這最常用於 const
的過載,但也可以用於 volatile
和 const volatile
的過載。這是因為所有非靜態成員函式都將 this
作為隱藏引數,cv-qualifiers 應用於該引數。這最常用於 const
的超載,但也可用於 volatile
和 const volatile
。
這是必要的,因為只有當成員函式至少與呼叫它的例項一樣符合 cv 限定時才能呼叫它。雖然非 const
例項可以同時呼叫 const
和非 const
成員,但 const
例項只能呼叫 const
成員。這允許函式根據呼叫例項的 cv 限定符具有不同的行為,並允許程式設計師通過不提供具有該限定符的版本來禁止不期望的 cv 限定符的函式。
具有一些基本的 print
方法的類可能會像這樣過載:
#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-qualifiers)修改為狀態,從而使程式碼更安全且更易讀。
class ConstCorrect
{
public:
void good_func() const
{
std::cout << "I care not whether the instance is 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(); // Good. Can be called from const or non-const instance.
cc.bad_func(); // Error. Can only be called from non-const instance.
}
void const_incorrect_func(ConstCorrect& cc)
{
cc.good_func(); // Good. Can be called from const or non-const instance.
cc.bad_func(); // Good. Can only be called from non-const instance.
}
這種情況的一個常見用法是將訪問器宣告為 const
,將 mutator 宣告為非 const
。
在 const
成員函式中不能修改類成員。如果你確實需要修改某個成員,例如鎖定 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;
};