2 minute read

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으로 해야하는 가에 혼란이 온다.

✏️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을 선언할 때는 어차피 하나만
      만들어져서 공유되어 사용되는 것이니 이니셜라이저를 통해 초기화하는 것이 이상하다.

➕ 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에서 num2mutable로 선언되어있으니 실수로 num1 = num2하는 실수를 방지 할 수는 있으나, 그러면 거의 모든 함수는 const로 대다수 변수는 mutable로 선언하는게 좋은 것이 된다.

    • 따라서, mutable은 꼭 필요할 때만 사용하자.

Tags: ,

Categories:

Updated: