언어 자료구조 알고리즘/Escort C++

[C++] 개체의 멤버와 형식의 멤버

언제나휴일 2016. 4. 15. 12:59
반응형

2.2.3 개체의 멤버와 형식의 멤버

 

 캡슐화된 멤버의 종류를 나누는 기준은 여러 기준이 있을 수 있습니다. 그중에 하나가 해당 멤버가 개체의 멤버인지 혹은 형식의 멤버인지로 구분을 할 수가 있습니다. 이러한 기준으로 구분할 때 형식의 멤버를 정적(static) 멤버라 부르고 개체의 멤버를 비 정적 멤버라 부릅니다.

 

 C++에서 정적 멤버는 형식 정의 내에서 해당 멤버를 static 키워드를 붙여 명시해야 합니다. static 키워드가 붙여 명시된 정적 멤버들은 개체에 종속적인 멤버가 아닌 형식에 종속적인 멤버가 됩니다. 예를 들어, 학생을 생성할 때 학생의 일련번호를 차례대로 부여한다고 할 때 학생의 일련번호는 각각의 학생마다 별도로 유지가 되어야 할 것입니다. 하지만 이번에 생성할 학생에게 어떠한 일련번호를 부여할 것인지는 각각의 학생 개체들에 보관하는 것이 아니라 학생 형식 스코프 내에 유일해야 할 것입니다. 심지어 학생 개체가 없다고 해도 이는 존재하게 됩니다.

 

 아래의 예제 코드를 보고 다시 한 번 생각해 봅시다. 종종 말이나 글로 설명을 듣고 보는 것보다 예를 보는 것이 더 많은 것을 느끼는 경우가 있습니다. 한 번 Look & Feel 하시고 다시 한 번 살펴보시기 바랍니다.

 

Stu.h

#pragma once

 

class Stu

{

    int num;

    static int last_num; //정적 멤버 필드

public:

    Stu(void);

    int GetNum();

    static int GetLastNum(); //정적 멤버 메서드             

};

 

 정적 멤버는 형식 정의를 할 때 멤버 앞에 static 키워드를 명시해야 합니다. 위의 Stu.h를 보면 last_num 멤버 필드와 GetLastNum 멤버 메서드는 정적 멤버가 됩니다. 여기에서 last_num은 가장 최근에 생성한 학생 번호를 보관하며 GetLastNum에서는 last_num 1 증가시키고 증가한 값을 반환함으로써 새로 생성되는 학생의 번호를 부여하는 역할을 할 것입니다.

 

 이 중에 정적 멤버 필드는 개체에 종속적이지 않기 때문에 개체가 생성된다고 해당 멤버 필드를 위해 메모리가 할당되지 않습니다. 이와 같은 정적 멤버 필드는 CPP소스 파일에 반드시 선언문이 있어야 합니다. 그리고 정적 멤버를 소스 파일(CPP 파일)에서 구체적으로 선언 및 정의를 할 때에는 static 키워드를 생략합니다. 다음의 구현 예를 살펴보시기 바랍니다.

 

Stu.cpp

#include "Stu.h" 

int Stu::last_num;  //static 멤버 필드는 멤버 필드 선언을 해야 함, 선언문에서 static 키워드 사용 안 함 

Stu::Stu(void)

{

    last_num++;

    num = last_num;

int Stu::GetNum()

{

    return num;

}

int Stu::GetLastNum()  //static 멤서 메서드 구현 정의에서는 static 키워드 사용 안 함

{

    return last_num;

}

 

 그리고 이처럼 정의된 Stu 형식의 정적 멤버 메서드 중에 노출된 멤버에 접근을 할 때에는 형식명으로 접근할 수 있습니다. 정적 멤버는 개체에 종속적인 멤버가 아니라 형식에 종속적인 멤버이기 때문입니다. 다음의 사용 예를 살펴보세요.

 

Program.cpp - 사용 예

#include <iostream>

using std::cout;

using std::endl;

#include "Stu.h"

void main()

{

    cout<<"현재 학생 수:"<<Stu::GetLastNum()<<endl;

    Stu *stu = new Stu();

    cout<<"학생번호:"<<stu->GetNum()<<endl;

 

    cout<<"현재 학생 수:"<<Stu::GetLastNum()<<endl;

 

    Stu *stu2 = new Stu();

    cout<<"학생번호:"<<stu->GetNum()<<endl;

 

    delete stu;

    delete stu2;

}

 

 사용 예를 보시면 GetLastNum메서드에 접근을 할 때 Stu 형식 명과 스코프 연산자(::)를 통해 접근하고 있음을 알 수 있습니다.

 

 마지막으로 정적 멤버 메서드에서는 비 정적 멤버 메서드를 호출할 수가 없습니다. 비 정적 멤버 메서드에서는 해당 개체의 멤버 필드의 값을 변경할 수도 있는데 비 정적 멤버 메서드에서는 어떠한 개체에 종속적인 것이 아니므로 비 정적 멤버 메서드를 호출할 수가 없습니다.

 

 다음을 보면 정적 멤버 메서드인 GetLastNum에서 비 정적 멤버 메서드인 GetNum을 호출하였을 때 오류가 나는 것을 확인할 수 있습니다.


비정적 멤버 함수를 잘못 호출했습니다.

[그림 2.9]


2장 캡슐화 Part1 

2장 캡슐화 Part2 

(모든 동영상 강의는 무료입니다.)

반응형