공부/C++

6. 접근지정자, const 객체, static 멤버

bokob 2024. 4. 18. 18:41

6.1 접근 지정자

접근지정자

캡슐화의 목적

  • 객체 보호, 보안
  • C++에서 객체의 캡슐화 전략
    • 객체의 상태를 나타내는 데이터 멤버(멤버 변수)에 대한 보호
    • 중요한 멤버는 다른 클래스나 객체에서 접근할 수 없도록 보호
    • 외부와의 인터페이스를 위해서 일부 멤버는 외부에 접근 허용

멤버에 대한 3가지 접근 지정자

  • private: 디폴트
    • 동일한 클래스의 멤버 함수에만 제한함
    • 클래스 밖에서 직접 접근 불가
  • protected
    • 클래스 자신과 상속받은 자식 클래스에만 허용
  • public
    • 모든 다른 클래스에 허용, 클래스 밖에서 직접 접근 가능
class Sample{
private:
    // private 멤버 선언
protected:
    // protected 멤버 선언
public:
    // public 멤버 선언
};
접근 지정자 해당 클래스의
멤버함수에서의 접근
파생클래스의
멤버함수에서에의 접근
클래스 밖에서의 접근
private O X X
protected O O X
public O O O
  • 클래스 안: 클래스 정의의 내부와 멤버 함수의 구현
  • 클래스 밖: 전역 함수 정의나 다른 클래스의 정의, 클래스로 만들어진 객체

 

멤버의 접근 지정에 따른 접근성

 

중복 접근 지정과 디폴트 접근 지정

접근 지정 중복

class Sample{
private:
    int x, y;
public:
    Sample();
private:
    bool checkXY();
};

 

디폴트 접근 지정: private

class Circle{
    int radius;
public:
    Circle();
    Circle(int r);
    double getArea();
};

*/
위 코드와 같다.
class Circle{
private:
    int radius;
public:
    Circle();
    Circle(int r);
    double getArea();
};

*/

 

C++ 구조체

C++ 구조체

  • 상속, 멤버, 접근 지정 등 모든 것이 클래스와 동일
  • 클래스와 유일하게 다른 점
    • 구조체의 디폴트 접근 지정 - public
    • 클래스의 디폴트 접근 지정 - private
struct StructName{
private:
    // private 멤버 선언
protected:
    // protected 멤버 선언
public:
    // public 멤버 선언
};

C++에서 구조체를 수용한 이유?

  • C++언어와의 호환성 때문
    • C의 구조체 100% 호환 수용
    • C 코드를 그대로 가져다 쓰기 위해

구조체 객체 생성

  • struct 키워드 생략
StructName stObj;      // (O) C++ 구조체 객세 생성
struct StructName Obj; // (X) C 언어의 구조체 객체 생성

 

구조체와 클래스의 디폴트 접근 지정 비교

// 구조체에서 디폴트 접근 지정은 public
struct Circle{
    Circle();
    Circle(int r);
    double getArea();
private:
    int radius;
};

// 클래스에서 디폴트 접근 지정은 private
class Circle{
    int radius;
public:
    Circle();
    Circle(int r);
    double getArea();
};

 

접근자 함수(accessor function)

접근자 함수

  • public 접근 권한을 갖는 멤버 함수
  • 클래스의 멤버 변수에 대한 접근을 도와주는 기능 제공
  • 접근자 함수는 보통 get 함수(값 리턴)와 set 함수(값 설정)로 구현됨
class Sample{
int mem;
public:
    int getMem();
    void setMem(int value);
};

// get 함수
int Sampel::getMem(){
    return mem; 
}

// set 함수
void Sample::setMem(int value){
    mem = value;
}

 

접근자 함수의 장점

다양한 레벨의 접근 권한 설정 가능

  • 멤버 변수를 public으로 지정하면 클래스 밖에서 멤버 변수에 대한 모든 접근을 허용하게 된다.
  • 접근자 함수를 사용할 때는 get 함수만 정의할 수 있고, set 함수만 정의할 수도 있고, get/set 함수를 모두 정의할 수도 있고, get/set 함수를 모두 정의하지 않을 수도 있다.

 

멤버 변수의 값을 변경하거나 읽어올 때, 멤버 변수의 값에 대한 유효성 검사 가능

bool Circle::setRadius(int r){
    if(r > 30) return false;
    radius = r;
    return true;
}

 

6.2 const 객체와 const 멤버함수

const 객체

const 객체

멤버 변수의 값을 변경할 수 없음

  • const 객체에는 대입할 수 없음
Circle pizza1(5);
const Circle pizza2; // 디폴트 생성자로 초기화
pizza2 = pizza1;     // const 객체에는 대입할 수 없으므로 컴파일 에러
  • const 멤버 함수만 호출 가능 -> const 멤버 함수를 지정할 필요가 있다.

const 객체의 사용

  • 객체를 함수의 입력 인자로 전달할 때 주로 사용
void ShowData(Circle& s);
void ShowData(const Circle& s); // s는 입력 인자, 원본 데이터를 변경할 수 없음을 보장

 

const 객체 사용 예

class CellPhone
{
public:
    int bell_mode;
    void Call(int quick_num);
    
    // const 멤버 함수라는 뜻. 함수 내에서 멤버 변수를 못바꾼다는 것을 보장
    void ShowRecentCall() const;
};

void main()
{
    const CellPhone myPhone;
    
    myPhone.bell_mode = 3; // 오류
    myPhone.Call(1);       // 오류
    
    // const 객체는 const 멤버 함수만 호출할 수 있다
    myPhone.ShowRecentCall();
}

 

const 멤버 함수

객체의 값을 변경하지 않기로 약속하는 멤버 함수

  • "이 함수에서는 멤버 변수의 값을 변경하지 않으므로, const 객체가 이 멤버함수를 호출해도 안전하다."는 의미
  • 클래스의 사용자에게 멤버 함수에 대한 명확한 정보를 제공

const 멤버 함수로 지정하는 방법

  • 함수의 선언과 정의 양쪽 모두에 const 키워드 지정
class 클래스 이름{
    멤버 함수 선언 const;
};
리턴형 클래스이름:: 멤버함수이름(인자리스트) const
{
}

const 멤버 함수 안에서는

  • 멤버 변수의 값 변경 불가능 / 디른 일반 멤버 함수 호출 불가능

 

const 멤버 함수의 의미

  • 멤버 함수를 const로 만드는 것의 의미
  • 다른 개발자가 "이 함수는 멤버 변수의 값을 변경하지 않는구나" 라고 생각하게 만든다.
  • 실수로 멤버 변수의 값을 바꾸려고 하면 컴퓨터가 오류 메시지를 통해서 알려준다.
  • const 객체를 사용해서 이 함수를 호출할 수 있다.

번외) const를 왜 뒤에다 붙일까? -> 앞에다 붙이면 리턴 타입에 const가 적용되는 것으로 되기 때문

 

6.3 static 멤버

static 멤버와 non-static 멤버의 특성

static

  • 변수와 함수에 대한 기억 부류의 한 종류
    • 생명 주기 - 프로그램이 시작될 때 생성, 프로그램 종료 시 소멸
    • 사용 범위 - 선언된 범위, 접근 지정에 따름

클래스의 멤버

  • static 멤버
    • 프로그램이 시작할 때 생성
    • 클래스 당 하나만 생성, 클래스 멤버라고 불림
    • 클래스의 모든 인스턴스(객체)들이 공유하는 멤버
  • non-static 멤버
    • 객체가 생성될 때 함께 생성
    • 객체마다 객체 내에 생성
    • 인스턴스 멤버라고 불림

 

static 멤버선언

멤버의 static 선언

class Person{
public:
    double money;
    void addMoney(int money){
        this->money += money;
    }
    
    static int sharedMoney;       // static int sharedMoney = 10; (X)
    static void addShared(int n){
        sharedMoney += n;
    }
};

// static 변수 공간 할당, 프로그램의 전역 공간에 선언
// 선언하면 다음과 같이 정의(초기화)가 반드시 필요
int Person::sharedMoney = 10;

// static 멤버 변수는 생성자로 초기화 못한다.
// 객체로도 접근되고, 클래스로도 접근 가능

static 멤버 변수 생성

  • 전역 변수로 생성. 전체 프로그램 내에 한 번만 생성

static 멤버 변수에 대한 외부 선언이 없으면 다음과 같은 링크 오류

 

static 멤버와 non-static 멤버의 관계

static 멤버 함수 안에서는 non-static 멤버 사용 불가능

 

static 멤버와 non-static 멤버 비교

항목 non-static 멤버 static 멤버
선언 사례 class Sample{
    int n;
    void f();
};
class Sample{
    static int n;
    static void f();
};
공간 특성 멤버는 객체마다 별도 생성
- 인스턴스 멤버라고 부름
멤버는 클래스 당 하나 생성
- 멤버는 객체 내부가 아닌 별도의 공간에 생성
- 클래스 멤버라고 부름
시간적 특성 객체와 생명을 같이 함
- 객체 생성 시에 멤버 생성
- 객체 소멸 시에 함께 소멸
- 객체 생성 후 객체 사용 가능
프로그램과 생명을 같이 함
- 프로그램 시작 시 멤버 생성
- 객체가 생기기 전에 이미 존재
- 객체가 사라져도 여전히 존재
- 프로그램이 종료될 때 함께 소멸
공유의 특성 공유되지 않음
- 멤버는 객체 별로 따로 공간 유지
동일한 클래스의 모든 객체들에 의해 공유됨

 

static 멤버 사용: 객체의 멤버로 접근

정적 멤버 변수

  • 같은 클래스의 객체들 사이에 공유되는 멤버 변수
  • 보통 멤버처럼 접근할 수 있음
  • 클래스 이름과 범위 지정자(::)으로 접근 가능
Sample s;
strcpy(s.name, "HH");
strcpy(Sample::name, "HH");

정적 멤버 함수

  • 객체 없이 호출할 수 있는 멤버 ㅎ마수
  • 보통 멤버함수처럼 객체이름이나 포인터로 접근 가능
  • 클래스 이름과 범위 지정자(::)으로 접근 가능
  • this 포인터가 없음 <- '객체' 자신을 뜻하기 때문
    • 멤버 함수는 객체의 소유가 아님
Sample* s1;
s1 = &s;
s1->showName();
s1::showName();

 

static 멤버는 객체 이름이나 객체 포인터로 접근

  • 보통 멤버처럼 접근할 수 있음
/*
객체.static 멤버
객체포인터->static 멤버
*/
  • Person 타입의 객체 s와 포인터 p를 이용하여 static 멤버를 접근하는 예
Person lee;
lee.sharedMoney = 500; // 객체.static멤버 방식

Person *p;
p = &lee;
p->addShared(200); // 객체포인터->static멤버 방식

 

static 멤버 사용: 클래스명과 범위 지정 연산자(::)로 접근

클래스 이름과 범위 지정 연산자(::)로 접근 가능

  • static 멤버는 클래스마다 오직 한 개만 생성되기 때문
// 클래스명::static 맴버
han.sharedMoney = 200; // Person::sharedMoney = 200;
lee.addShared(200);    // Person::addShared(200);
  • non-static 멤버는 클래스 이름을 접근 불가
Person::money = 100;   // 컴파일 오류. non-static 멤버는 클래스 명으로 접근 불가
Person::addMoney(200); // 컴파일 오류. non-static 멤버는 클래스 명으로 접근 불가

 

static 활용

static의 주요 활용

  • 전역 변수나 전역 함수를  클래스에 캡슐화
    • 전역 변수나 전역 함수를 가능한 사용하지 않도록
    • 전역 변수나 전역 함수를 static으로 선언하여 클래스 멤버로 선언
  • 객체 사이에 공유 변수를 만들고자 할 때
    • static 멤버를 선언하여 모든 객체들이 공유

 

static 멤버 함수는 static 멤버만 접근 가능

  • static 멤버 함수가 접근할 수 있는 것
    • static 멤버 함수
    • static 멤버 변수
    • 함수 내의 지역 변수
  • static 멤버 함수는 non-static 멤버에 접근 불가
    • 객체가 생성되지 않은 시점에서 static 멤버 함수가 호출될 수 있기 때문

 

non-static 멤버 함수는 static에 접근 가능

class Person{
    public: double money;
    static int sharedMoney;
    // ...
    int total(){ // non-static 함수는 non-static이나 static 멤버에 모두 접근 가능
        return money + sharedMoney;
    }
};

 

 

'공부 > C++' 카테고리의 다른 글

8. 함수와 참조, 복사생성자  (1) 2024.05.14
7. 여러가지 객체의 생성방법  (0) 2024.05.14
5. 생성자와 소멸자  (0) 2024.04.11
4. 클래스와 객체의 기본  (0) 2024.04.09
3. 개선된 함수 기능  (0) 2024.03.31