ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ch01-03. const 들이대기 2
    effective c++ & c++ 2022. 8. 31. 21:33

    상수 멤버 함수

    해당 멤버 함수가 상수 객체에 의해 호출될 함수임을 의미.

     

    상수 멤버 함수의 의미

    1. 물리적 상수성(=비트 수준의 상수성)

    2. 논리적 상수성

     

    물리적 상수성(=비트 수준의 상수성)

    어떤 멤버 함수가 그 객체의 어떤 데이터 멤버도 건드리지 않아야 정적 멤버 함수임을 인정.

    컴파일러는 테이터 멤버에 대입 연산의 수행 여부만 파악하면 된다.

    class CTextBlock
    {
    private:
    	char* pText;
    public:
    	char& operator(size_t pos) const
    	{
    		return pText[pos];
    	}
    };
    
    ...
    
    const CTextBlock cctb("Hello");
    char *pc = &cctb[0];
    *pc = 'J'; // 물리적 상수성은 만족하지만 멤버함수 반환형이 const가 아니여서 참조를 통한 값 변경 가능.

     

    논리적 상수성

    상수 멤버 함수라 해서 객체의 한 비트도 수정할 수 없는 것이 아니라, 일부 몇 비트 정도는 바꿀 수 있되

    그것을 사용자측에서 알아채지 못하게 한다면 상수 멤버 자격이 있음을 의미.

     

    mutable 키워드를 통해 구현 가능하다.

    class CTextBlock
    {
    private:
    	char *pText;
        mutable size_t textLength; //pText의 길이값이기 때문에 사용자가 이를 직접 수정할 수 없게 해야함.
        mutable bool lengthIsValid;
    public:
    	size_t length() const;
    };
    
    size_t CTextBlock::length() const
    {
    	if(!lengthIsValid)
        {
        	textLength = strlen(pText);
            lengthIsValid = true;
       	}
        
        return textLength;
    }

    ** mutable 키워드는 const가 붙은 구조체나 클래스,멤버 함수에서 특정 멤버 변수의 수정을 허용하는 키워드이다.

    mutable int a;
    int mutable b;

    멤버 변수의 자료형 앞,뒤에 붙는 게 동일한 의미이고 가능하다.

     

     

    상수 멤버 함수가 중요한 이유

    1. 해당 멤버 함수로 구성된 클래스의 객체를 변경할 수 있는 함수를 구분.

    2. 상수 객체를 사용 가능하게 함. (상수 객체는 상수 멤버 함수만 호출 가능하기 때문이다.)

     

    ** 상수 객체가 생성되는 경우에는

    1. 상수 객체에 대한 포인터로 객체가 전달되는 경우

    2. 상수 객체에 대한 참조자로 객체가 전달되는 경우 -> 프로그램의 실행 성능을 높이는 핵심 기법 중 하나.

    두가지가 있다. 

    void print(const TextBlock& tb) // 상수 객체로 사용된 tb
    {
    	cout<<tb[0];
        ...
    }

     

    const의 있고 없고의 차이만으로 멤버 함수의 오버로딩이 가능하다.

    class TextBlock
    {
    private:
    	string text;
    public:	
    	const char& operator[](size_t pos) const
        {
        	return text[pos];
        }   
        char& operator[](size_t pos)
        {
        	return text[pos];
        }   
    };

     

    상수 멤버 함수와 비상수 멤버함수가  const를 제외한 모든 기능이 동일할 경우

     

    비상수 버전의 멤버함수에서 상수 멤버 함수를 호출하도록 만든다.

    (상수 멤버 함수에서 비상수 멤버 함수를 호출하는 것은 안정성에 문제가 된다.)

     

    class TextBlock
    {
    public:
    	const char& operator[](size_t pos) const
        {
        	...
            return text[pos];
        }
        
        char& operator[](size_t pos)
        {
    		return 
            	const_cast<char&> //상수 operator[]의 반환값에서 const를 떼어내는 캐스팅
                (
                	static_cast<const TextBlock&>(*this)[pos] //*this에 const를 붙이는 캐스팅
                );
        }
        ...
    };

     

    # const_cast와 static_cast 에 대해 복습해보자.

     

    - 형 변환 연산자

     

    1. static_cast 연산자

     

    - static_cast <T> (변환의 대상) 형태로 사용.

    - T에는 객체의 포인터 또는 참조형이 와야한다.

    - 유도 클래스의 포인터 및 참조형 데이터를 기초 클래스의 포인터 및 참조형 데이터로 형 변환 가능.

    - 기초 클래스의 포인터 및 참조형 데이터를 유도 클래스의 포인터 및 참조형 데이터로 형 변환 가능.

    class Car
    {
    ...
    }
    
    class Truck : public Car
    {
    ...
    }
    
    int main()
    {
    	Car* pcar2=new Car(120);
        Truck* ptruck2=static_cast<Truck*>(pcar2);
    }

    - 기본 자료형 데이터 간의 형 변환에도 사용 된다.

    -  상수 객체 -> 비상수 객체로의 변환을 허용하지 않는다.

     

    2. const_cast 연산자

     

    - const의 성향을 삭제하는 형 변환을 목적으로 한다.

    - const_cast<T>(expr)

    - const 선언으로 인한 형의 불일치가 발생해서 인자의 전달이 불가능한 경우에 유용하게 사용된다.

Designed by Tistory.