본문 바로가기
프로그래밍

[C++ 정복하자] 클래스의 기본

by _BlankSpace 2017. 5. 20.

[C++ 정복하자] 를 위한 세 번째 정리 포스팅입니다. 이 글은 제가 공부한 내용을 토대로 정리하는 글이므로, 원하시는 내용이나

보시는 분보다 낮은 실력일수도 있습니다. 부족하다고 생각하시는 점들은 댓글로 남겨주시면 최대한 보완하는 데 최선을 다하겠습니다.


목차로 돌아가기


이번 장은 본격적으로 C에서는 볼 수 없고, C++이기에 느끼고 사용할 수 있는 클래스 내용을 주로 다룰 예정입니다. 이러한 클래스를 잘 느끼기 위해서는 구조체도 사용해보고, 특징을 알아야 될 것으로 생각합니다. 그러므로 구조체를 이해하시고, 글을 읽어주시기 바랍니다.


 1. C++의 구조체. 

구조체는 프로그램을 만들 때, 굉장히 유용하고 중요한 역할을 하고 있습니다. 게임 캐릭터를 예로 들어볼까요? 게임 속의 캐릭터는 간단하게는 닉네임, 아이디, 패스워드부터 몇 번의 강화를 성공한 아이템까지 이러한 정보를 하나로 묶어야 누구의 것인지 확실하게 파악할 수 있을 것입니다. 자기가 소유한 아이템을 다른 캐릭터에 저장할 수는 없겠죠?

그럼 앞에서 게임 캐릭터를 예로 들었으니, 간단하게 구조체를 구성하여 설명하겠습니다.


다음의 구조체는 슈퍼마리오가 가진 상태를 표현하는 구조체라고 생각하겠습니다.


struct Mario

{

    int age;        ///<

    char status;    ///<마리오의 상태.

    int speed;      ///<

};


마리오의 상태는 몇 가지 안되므로 char형을 사용하였습니다. 그럼 이러한 구조체를 이용하여 간단한 구조체의 내용을 출력해보겠습니다.

CppStruct.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
 
enum { small = 0, big, flower, star, fly };
 
struct Mario
{
    int age;        ///<
    char status;    ///<마리오의 상태.
    int speed;      ///<
};
 
int main(void)
{
    Mario p1;
    p1.age = 15;
    p1.status = big;
    p1.speed = 0;
 
    cout << "age = " << p1.age << endl;
    cout << "status = " << (int)p1.status << endl;
    cout << "speed = " << p1.speed << endl;
    return 0;
}
cs


결과:

 >> age = 15

 >> status = 1

 >> speed = 0

구조체를 아시는 분이라면 쉽게 보실 수 있을만한 코드입니다. 그러므로 자세한 코드 설명은 넘어가도록 하겠습니다. (혹시 필요하신 분은 댓글 남겨주시기 바랍니다.)


그런데 여기서 의문점 하나가 있습니다.

구조체 안에는 위의 예제처럼 자료형만 넣어야 할까요? 함수는 넣을 수 없을까요?

답은 함수도 넣을 수 있습니다. 또한, 구조체 안에 enum 상수도 선언할 수 있습니다.


다음 예제를 통해 확인해보겠습니다.

CppStruct.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
 
#define SPEED_MIN 0
#define SPEED_MAX 99
 
using namespace std;
 
enum
{
    small = 0,
    big,
    flower,
    star,
    fly
};
 
 
struct Mario
{
    enum
    {
     down  = -10,
     up    = 10,
    };
    int age;        ///<
    char status;    ///<마리오의 상태.
    int speed;        ///<
    void speedAccel(bool upAndDown);
    void printMarioStatus();
};
 
void Mario::speedAccel(bool upAndDown)
{
    if (upAndDown) {
     speed += up;
    }
    else {
     speed += down;
    }
    cout << "current speed : " << speed << endl;
}
 
void Mario::printMarioStatus()
{
    cout << "age = " << age << endl;
    cout << "status = " << (int)status << endl;
    cout << "speed = " << speed << endl;
}
 
int main(void)
{
    Mario p1, p2;
    p1.age = 15;
    p1.status = big;
    p1.speed = SPEED_MIN;
    
    p1.printMarioStatus();
    p1.speedAccel(true);
    p1.printMarioStatus();
    p1.speedAccel(false);
    p1.printMarioStatus();
    return 0;
}

cs


결과:

 >> age = 15

 >> status = 1

 >> speed = 0

 >> current speed : 10

 >> age = 15

 >> status = 1

 >> speed = 10

 >> current speed : 0

 >> age = 15

 >> status = 1

 >> speed = 0



위의 예제와 같이 구조체 안에 enum 설정도 가능하고, 함수도 정의할 수 있다는 것을 보실 수 있습니다. 또한, 위의 예제에서 32 ~ 48줄을 참고하시면 구조체 내부가 아닌 외부에서도 함수를 정의할 수 있다는 것을 볼 수 있습니다.


이것은 가독성에도 도움이 될 수 있기 때문에 잘 사용한다면 좋은 효과를 얻을 수 있으리라 생각합니다. 특히, cpp 와 h 파일을 나누어서 개발할 때면 더 유용할 것으로 생각합니다.


그렇다면 여기서 의문이 드시는 분이 계실 수 있습니다. 이건 클래스와 별 다를 바 없는 것 같은데...? 라고 생각하실 수도 있습니다.

물론 그렇게 생각하지 않으셨다면.. 그냥 넘어가셔도 됩니다. ㅋㅋ


이번 장에서는 클래스에 대해서 자세히는 설명하지 않겠지만, 클래스와 구조체의 가장 큰 차이점이 있습니다. 그것은 접근 제어 지시자 또는 접근 제어 레이블 이라는 것이 존재한다는 것입니다.


 2. 접근 제어 지시자(레이블) 

위에서 설명했듯이, 클래스와 구조체의 가장 큰 차이점은 접근 제어 지시자입니다. 가뜩이나 복잡한 언어인데.. 무엇인가 어려운 용어가 튀어나왔습니다.. 하지만, 결코 어렵지 않은 내용입니다. 아, 물론 중요한 내용이기도 하구요. 


간단하게 말하자면, 클래스 내부에서 정의하는 자료형이나 함수의 공개 범위를 설정한다고 생각하면 되겠습니다.

이러한 접근 제어 지시자는 크게 3가지로 나뉩니다.

- public : 해당 클래스 뿐만 아니라 어디에서든지 접근을 허용합니다.

- protected : 클래스 간에 상속 관계일 때, 자식 클래스에서 접근이 가능합니다.

- private : 오로지 정의된 클래스에서만 접근을 허용합니다.


간단한 예제로 설명을 계속하겠습니다.


CppClass.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Mario
{
    enum
    {
        down  = -10,
        up    = 10,
    };
private:
    int age;        ///<
    char status;    ///<마리오의 상태.
    int speed;      ///<
public
    int Age(void) { return age; } 
    void setAge(int _age) { age = _age; }
    char Status(void) { return status; }
    void setStatus(char _status) { status = _status; }
    int Speed(void) { return speed; } 
    void setSpeed(int _speed) { speed = _speed; }
    void speedAccel(bool upAndDown);
    void printMarioStatus();
};
 
int main(void)
{
    Mario p1, p2;
    p1.setAge(15);
    p1.setStatus(big);
    p1.setSpeed(SPEED_MIN);
 
    cout << "age : " << p1.Age() << " status : " << (int)p1.Status() << " speed : " << p1.Speed() << endl;
    return 0;
}
cs

(중간 함수는 위의 예제와 같으므로 생략하였습니다.)


결과:

 >> age : 15 status : 1 speed : 0

물론, 이 예제는 상속의 개념을 아직 적용하지 않았기 때문에 접근 제어 지시자를 정확하게 설명하기는 어렵습니다. 이 예제로 설명하고자 하는 의도는 Class 내부에서 private으로 자료형을 정의하고 함수는 public으로 정의했다는 점입니다.

이게 무슨 뜻이냐구요? 지금부터 설명하겠습니다.!

위에서 설명했듯이, private과 public 단어 의미에서부터 느낄 수 있듯이 서로 상반되는 느낌입니다. 굳이, 자료형을 private으로 설정한 이유는 함수 내부, 즉 여기에서는 main 함수에서 클래스 내부의 값을 직접 접근할 수 없도록 하기 위함입니다. 따라서, Mario라는 클래스의 값을 변경하고자 하면 Setter 함수 (이 클래스에서는 setAge, setStatus, setSpeed 즉, 값을 설정하기 위한 함수) 를 이용하고, 값을 이용하고자 하면 Getter ( 이 클래스에서는 Age, Status, Speed) 함수를 이용하여 Mario 클래스의 값을 사용할 수 있게 되는 겁니다.

이러한 특징을 C++의 중요한 특징인 정보은닉이라고도 할 수 있습니다.


이상, 이번 포스팅을 마치겠습니다. 궁금한 점이나 부족한 점이 있다면 댓글 남겨주시길 바랍니다. 


참고 자료 : 윤성우의 열혈 C++ 프로그래밍

구글링


목차로 돌아가기


제 글이 도움이 되셨거나 공감이 되시는 부분이 있으셨다면, 밑에 있는 공감 버튼 한 번씩 꾸욱 눌러주시면 감사하겠습니다.


공감 버튼은 저에게 큰 도움이 됩니다. 감사합니다.

'프로그래밍' 카테고리의 다른 글

[C++] switch case문 jump to case label 오류 문제 해결 방법  (0) 2019.01.20
[C++11] auto 정리  (0) 2017.05.24
[c++ 정복하자] 목차  (0) 2017.05.13
[STL] Vector 정리  (0) 2017.04.14
STL vector sort(벡터 정렬) (2)  (0) 2017.04.08

댓글