본문 바로가기
[공부]/C++

[C++] 기본 정리 16 - OOP의 캡슐화(프렌드, 정적 멤버, 상수 멤버)

by 개발꿈냥무 2024. 2. 25.

OOP 캡슐화 - 프렌드 (friend)

해당 객체의 멤버 함수가 아닌 함수가 private 멤버에 접근할 수 있도록

friend 라는 새로운 접근 제어 키워드를 제공

  • 지정한 대상에 한해, 해당 객체의 모든 멤버에 접근할 수 있는 권한을 부여함
  • 전역 함수, 클래스, 멤버 함수의 세 가지 형태로 사용 가능
  • friend 키워드는 함수 원형에서만 사용해야 함 (함수 정의에서는 사용하지 않음)
  • 프렌드 선언은 클래스 선언부의 public, private, protected 영역 등 어디에나 위치 가능 (위치에 따른 차이 없음)

 

프렌드 함수 선언

원형)
friend 클래스이름 함수이름( 매개변수목록 );
  • 프렌드 함수는 클래스 선언부에 원형이 포함되지만, 클래스의 멤버 함수는 아님
  • 클래스 멤버 함수가 아니지만, 멤버 함수와 같은 접근 권한을 가짐

 

프렌드의 필요성 : 클래스에 대해 이항 연산자를 오버로딩할 때 자주 발생

      (멤버가 아닌 함수를 사용하면 해당 객체의 private 멤버에 접근할 수 없으므로)

사각형 나타내는 Rect 클래스를 정의하면서,
크기를 조절하기 위해 곱셈 연산자를 오버로딩하는 예)
class Rect{
private:
	double height_;
	double width_;
public:
	Rect(double height, double width); // 생성자
	Rect operator*(double mul) const;
	friend Rect operator*(double mul, const Rect& origin); // 프렌드 함수
};

...

Rect Rect::operator*(double mul) const
{
	return Rect(height_ * mul, width_ * mul);
}
Rect operator*(double mul, const Rect& origin) { return origin * mul; }

 

 

cf) 멤버 함수 원형의 맨 마지막에 const 키워드를 추가하면, 멤버 함수를 상수 멤버 함수로 정의 가능

(상수 멤버 함수 : 자신이 호출하는 객체를 수정하지 않는 읽기 전용 함수)

 

 

 

프렌드 클래스 : 해당 클래스의 모든 멤버 함수가 특정 클래스의 프렌드인 클래스 

두 클래스가 기능상으로 서로 밀접하고, 상대의 private 멤버에 접근해야만 한다면

클래스 자체를 friend로 선언하는 게 좋음!

프렌드 클래스 선언 문법)
friend class 클래스이름;

예시)
class Rect {
private: ...
public: 
	...
	friend class Display; // 프렌드 클래스 선언
	-> Display 클래스의 모든 멤버 함수는 Rect 클래스에 대한 프렌드 접근 권한을 부여받게 됨
};

 

 

 

프렌드 멤버 함수 : 해당 클래스의 특정 멤버 함수만을 프렌드로 지정하는 것

(프렌드 설정이 꼭 필요한 함수에만 접근을 허락하므로, 정보 은닉캡슐화 개념에 더욱 가깝게 구현 가능)

class Rect {
private: ...
public: 
	...
	friend void Display::ShowDiagonal(const Rect& target); // 프렌드 멤버 함수 선언
	-> Display 클래스의 ShowDiagonal() 함수만이 Rect 클래스의 모든 멤버에 접근할 수 있음
};

 

cf) 전방 선언 : 순환 참조를 피하기 위해 한 클래스를 다른 클래스의 앞에 미리 선언하는 것

 

 


정적 멤버 변수/함수 (static member variable)

  • 클래스에는 속하지만, 객체 별로 할당되는 게 아니라 클래스의 모든 객체가 공유하는 멤버
  • 정적 멤버 변수 : 해당 클래스의 모든 객체에 대해 하나의 데이터만이 유지/관리됨
    • 클래스 영역에서 선언되지만, 정의는 파일 영역에서 수행됨 -> 외부 연결을 가져서, 여러 파일에서 접근 가능
    • 클래스 멤버의 접근 제한 규칙이 적용되므로, 클래스 멤버 함수나 friend만이 접근할 수 있음
    • 모든 Person 객체가 공유하는 정적 멤버 변수 선언 예)
      class Person {
      private: ...
      public: 
      	static int person_count_; // 정적 멤버 변수 선언
      	...
      }
      
      int Person::person_count_ = 0; // 정적 멤버 변수의 정의 및 초기화
  • 정적 멤버 함수 : 해당 클래스의 객체를 생성하지 않아도, 클래스 이름만으로 호출 가능
    • 객체를 생성하지 않으므로, this 포인터를 갖지 않음
    • 특정 객체와 결합하지 않으므로, 정적 멤버 변수밖에 사용할 수 없음
    • 문법)
      1) 객체이름.멤버함수이름();   -> 일반 멤버 함수의 호출
      2) 클래스이름.멤버함수이름(); -> 정적 멤버 함수의 호출
      
      예시)
      class Person {
      private: ...
      public: 
      	static int person_count(); // 정적 멤버 함수의 선언
      	...
      };
      
      int Person::person_count() { // 정적 멤버 함수의 정의
      	return person_count_;
      }

 

 

상수 멤버 변수/함수

  • 상수 멤버 변수 : 한 번 초기화하면 그 값을 변경할 수 없는 멤버 변수
    • 변수의 타입 앞에 const 키워드를 사용하여 선언
    • 클래스 전체적으로 사용되는 중요한 상수를 상수 멤버 변수로 정의하면 좋음
  • 상수 멤버 함수 : 호출한 객체의 데이터를 변경할 수 없는 멤버 함수
    • 함수 원형 끝에 const 키워드를 사용하여 선언
    • 호출한 객체의 데이터를 단순 읽기만 하는 멤버 함수를 상수 멤버 함수로 정의하면 좋음
상수 멤버 변수 문법) const 타입 멤버변수이름;
상수 멤버 함수 문법) 함수원형 const;

 

 

 

 


참고)

코딩의 시작, TCP School

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com