[열혈 C++] Chap06: Const, Friend, Static, Mutable
6-1. const에 대한 못다한 이야기
- const 함수는 오버로딩 되었을 때도, const 함수나 const 변수만 쓸 수 있다.
즉, 멤버함수가void SoSimpleFunc(){ cout <<"SimpleFunc : " << num << endl; } void SoSimpleFunc() const{ cout << "const SimpleFunc : "<< num << endl; }
- 이렇게 있을 때,
const SoSimple obj
는 const 함수를 호출하게 되고,SoSimple obj1
는 첫번째 함수를 호출한다.
- 이렇게 있을 때,
6-2. friend 친구친구
- A클래스가 B클래스를 대상으로 friend 선언을 하면, B클래스는 A클래스의 private 멤버에 직접 접근할 수 있다.
- 이때, B클래스도 A클래스에 friend 선언을 해주면, A도 B클래스의 private 멤버에 접근이 가능해진다.
- 전역/멤버 함수에도 friend 선언은 가능하다.
✏️friend는 언제?
- friend는 객체지향의 특징인 정보은닉을 무너뜨리기 때문에 남용하면 곤란하다.
- 필요할 때 신중하게 사용해야 한다.
- 연산자 오버로딩!
6-3. static
- 전역변수에서 static : 선언된 파일 내에서만 참조 허용
- 함수 내에서 static : 한번만 초기화되고, 지역변수와 달리 함수를 빠져나가도 소멸되지 않음
✏️static 멤버변수(클래스 변수)
-
클래스 내에서 딱 하나만 만들어지는 변수로, A클래스의 객체들(a,b,c…)이 많이 만들어질 때, static변수는 객체들 통틀어서 딱 하나만 존재한다. 그리고 객체들이 공유한다.
클래스 내의 전역변수라고 생각하면 될 것 같다. 실제로 전역변수와 생성, 소멸 시점이 같다. -
그렇지만 전역변수로 안쓰고
private static
으로 쓰는 이유는, 아무한테나 공유하고 싶지는 않아서!
딱 하나만 존재하면 좋겠는데, 그렇다고 아무 클래스나 접근하는 건 싫고 자기 클래스에서만 공유해서 쓰고 싶을 때 선언해주면 유용할 듯 하다. -
물론
public static
으로 쓰면 다른 클래스에서 접근할 수 있다.
✏️static 멤버변수 초기화
-
생성자에서 초기화 하면 안되는 이유는, 객체가 생성될 때 마다 초기화되기 때문이다. 하나 공유해서 계속 써야하는데 의도치 않게 객체 만들때마다 다시 초기화 되면 당연히 쓰려는 목적에 어긋난다.
-
따라서,
int SoSimple::staticvar = 0;
이런 식으로 별도로 써준다.
✏️static 멤버함수
- static 멤버 변수와 동일하다.
- 선언된 클래스의 모든 객체가 공유
- public 선언시, 클래스 이름을 이용해 호출 가능
- 객체의 멤버로 존재하는 것이 아님
-
객체의 멤버로 존재하지 않는다는 것이 무엇이냐!
static 멤버함수는 static이 선언되지 않은 멤버변수에 접근할 수 없다는 것이다.class SoSimple{ private: int num1; static int num2; public: SoSimple(int n): num1(n){} static void Adder(int n)[ num1+=n; //컴파일 에러 num2+=n; ] }
- 위의 예시를 보면 너무 당연하다. 클래스의 객체가 여러개일때, num2는 하나의 메모리에 할당되어 있겠지만,
num1은 객체마다 하나씩 가지고 있을텐데, Adder함수의 num1은 그럼 어느 num1으로 해야하는 가에 혼란이 온다.
- 위의 예시를 보면 너무 당연하다. 클래스의 객체가 여러개일때, num2는 하나의 메모리에 할당되어 있겠지만,
✏️const static
-
const 멤버변수는 초기화 한번 후에 값이 변하지 못하는 것이라 앞서 배웠듯 이니셜라이저를 통해 초기화 한다. 그러나 static이 선언된 const 멤버변수는 클래스 내에서 일반적인 변수 초기화 하듯이 할 수 있다.
class Simple{ public: const static int n1 = 0; const static int n2 = 1; const static int n3 = 3; }
- 생각해보면 당연한게, const 변수는 선언과 동시에 초기화되어야 하는데, static을 선언할 때는 어차피 하나만
만들어져서 공유되어 사용되는 것이니 이니셜라이저를 통해 초기화하는 것이 이상하다.
- 생각해보면 당연한게, const 변수는 선언과 동시에 초기화되어야 하는데, static을 선언할 때는 어차피 하나만
➕ mutable
- 키워드 mutable : “const 함수 내에서 값의 변경을 예외적으로 허용한다”
-
복습
+ const : 값 변경 허용X
+ explicit : 대입연산자로 객체 생성 및 초기화를 허용X -
빈도수 낮춰서 사용하는 것이 좋다!
class Simple{ private: int num1; mutable int num2; public: Simple(int n1, int n2): num1(n1), num2(n2){} void Copy() const{ num2 = num1; } }
-
위 상황처럼
Copy() const
에서num2
가mutable
로 선언되어있으니 실수로 num1 = num2하는 실수를 방지 할 수는 있으나, 그러면 거의 모든 함수는 const로 대다수 변수는 mutable로 선언하는게 좋은 것이 된다. -
따라서, mutable은 꼭 필요할 때만 사용하자.
-