const 구성원 함수, const member function

7449 단어 function
기원
지난주에 토크의 Online StatManager를 썼을 때 (사용자의 온라인 형식을 관리하는 클래스) 프라이빗 멤버가 있었어요.
private:

    OnlineType getStat(int userId) const ;

user의 온라인 형식을 읽는 데 사용합니다. 저는 이 member를 const를 위해 맵을 읽을 때 자물쇠를 추가합니다. 자물쇠는 자신이 정의한 클래스 구성원 boost::shared_mutex mu_; 관련 코드를 다음과 같이 캡처합니다.
 1 class OnlineStatManager {

 2 // ...

 3 private:

 4          OnlineType getStat(int userId) const;

 5          boost::shared_mutex mus_[POOL_NUM]; //  mutable boost::shared_mutex mus_[POOL_NUM];

 6 }

 7 OnlineType OnlineStatManager::getStat(int userId) const{

 8            //...

 9            ReadLock read(mus_[poolIndex]);

10            //...

11 }

12 //typedef boost::shared_lock<boost::shared_mutex> ReadLock; 

위의 9행 코드는 컴파일할 수 없습니다. ReadLock의 정의는 다음과 같습니다.
typedef boost::shared_lock<boost::shared_mutex>  ReadLock;

g++ 오류 메시지:
  boost::shared_lock::shared_lock (const boost::shared_mutex &) 의 호출에 일치하는 함수가 없습니다.
여기서 주의해야 할 것은,shared_lock의constructor는 모두reference를 전송하지만 아래 테스트 프로그램에서 const member function가 자신의 클래스 구성원을 사용할 때 const 인용으로 변하는 것을 볼 수 있습니다. 5행mus_성명에mutable을 추가하거나 getStat 성명과 정의를 삭제할 때const를 추가하면 됩니다.
 
const 구성원 함수
c++의 문법 차원에서 볼 때constclassobject는public의constmember(function)만 호출할 수 있으며, constmemberfunction는datamember의 값을 수정할 수 없습니다.
제 결론은 클래스의constmemberfunction에서 컴파일러는 클래스의 모든 구성원(field)을const유형으로 간주하여 컴파일하는 것입니다. (이것도 왜 const구성원 함수가 성명과 정의에서const키워드를 써야 하는지) 클래스 C의memberfunction에서,this의 행위는 다음과 같습니다.
C * const this; // non-const member function

const C * const this; // const member function

effective c++의 item21 이렇게 말합니다:use const whenever possible
그 중에서 두 개의 const 개념을 언급했는데bitwise constness and conceptual constness(위치 상량과 개념적 상량), 전자는 기본 유형에 대한 것이고 c++가 constness에 대한 정의이기도 하다. Class에 있어 const object는 공공적인const member(function)만 호출할 수 있고 const member funct는 클래스 대상의fields를 수정할 수 없지만 conceputual constness의 개념을 고려한다.C++standardcommission의 해결 방안은 바로mutable입니다. mutable는 클래스 구성원이constmemberfunction의 제한을 받지 않고 값을 부여받아 수정할 수 있습니다
use const wheneverpossible의 원칙은 여러 사람이 합작하여 프로그램을 쓸 때 이 원칙을 따라야 하며 이런 유형의 전환 오류를 자주 만날 수 있습니다
 
또한iterator로 constcontainer를 훑어볼 수 없습니다. const_iterator, 이거 아직 생각 안 해봤어요. 나중에 자세히 연구해 볼게요.
 
테스트 프로그램
테스트 프로그램 const_function.cpp, 약간의 난잡함, const T는 T를 변환할 수 있지만, const T & T로 변환할 수 없습니다 &
#include <iostream>

 // const int    int   int& ,   

 using namespace std;

 int global (int& num){

     num = num + 2;    

 }

 class Int{

 public :

         Int (int& i) :i_(i){

             cout << "Int 's constructor" << endl;    

         }

 

         Int () {

             cout << "Int 's default constructor" << endl;    

         }

 

         int i () const{

             return i_;    

         }

 private :

         int i_;

 };

 class WY{

 public :

         WY (int num) : num_(num) {

             cout << "WY's constructor WY(int num)" << endl;    

         }

         

         WY (Int& in) : in_(in) {

             cout << "WY's constructor WY(Int& in)" << endl;

             num_ = in.i();    

         }

 

         int get() const{

             cout << "int get() const" << endl;

             Int in(num_);

             WY w(in_);

             w.num_ = 7;

             int temp = global(num_);  // , temp global 

             return num_;

         }

 

 private :

         mutable int num_;

         mutable Int in_;

 };

 int main (){

     WY wy(5);

     int t = wy.get();

     cout << "t = " << t << endl;    

 }


 
코드는 두 개의 클래스, 하나의 전역 함수를 정의합니다. 주로 int WY::get ()const에서 자신의 두 개의 데이터 member를 매개 변수로 두 개의 클래스를 생성하고 전역 함수를 호출합니다.
만약 48,49 줄이 클래스 구성원을mutable로 성명하지 않았다면, 컴파일할 수 없습니다. 다음과 같은 컴파일 오류가 발생할 수 있습니다
const.cpp: In member function ‘int WY::get() const’:

const.cpp:36:15: error: no matching function for call to ‘Int::Int(const int&)’

const.cpp:36:15: note: candidates are:

const.cpp:13:3: note: Int::Int()

const.cpp:13:3: note:   candidate expects 0 arguments, 1 provided

const.cpp:9:3: note: Int::Int(int&)

const.cpp:9:3: note:   no known conversion for argument 1 from ‘const int’ to ‘int&’

const.cpp:7:7: note: Int::Int(const Int&)

const.cpp:7:7: note:   no known conversion for argument 1 from ‘const int’ to ‘const Int&’

const.cpp:37:12: error: no matching function for call to ‘WY::WY(const Int&)’

const.cpp:37:12: note: candidates are:

const.cpp:29:3: note: WY::WY(Int&)

const.cpp:29:3: note:   no known conversion for argument 1 from ‘const Int’ to ‘Int&’

const.cpp:25:3: note: WY::WY(int)

const.cpp:25:3: note:   no known conversion for argument 1 from ‘const Int’ to ‘int’

const.cpp:23:7: note: WY::WY(const WY&)

const.cpp:23:7: note:   no known conversion for argument 1 from ‘const Int’ to ‘const WY&’

const.cpp:39:26: error: invalid initialization of reference of type ‘int&’ from expression of type ‘const int’

const.cpp:4:5: error: in passing argument 1 of ‘int global(int&)’


이 오류 출력을 자세히 보면 오류는 원본 코드의 36, 37, 39줄에서 발생하고 오류 출력의 no matching function의 매개 변수는 인용입니다. 여기는 잠시 잘 모르겠습니다. 아래를 보시면 역시from'const int'to'int &','cont int'to'int &'를 보실 수 있습니다. get () 이 const 구성원 함수에서 두 구성원 int, int를 모두 const로 사용하고 있습니다.
수정 실행 결과
Int 's constructor Int()WY's constructor WY(int num)int get() constInt 's constructor Int(int i)WY's constructor WY(Int& in)t = 7
실행 결과에 따르면 WY 클래스 대상은 먼저 자신의 클래스 구성원인 Int in을 초기화하고 자신의 constructor를 실행합니다
참고http://en.wikipedia.org/wiki/Mutable,immutableobject에 대한 소개

좋은 웹페이지 즐겨찾기