티스토리 뷰
주의 사항!
- 이 글은 제가 직접 공부하는 중에 작성되고 있습니다.
- 따라서 제가 이해하는 그대로의 내용이 포함됩니다.
- 따라서 이 글은 사실과는 다른 내용이 포함될 수 있습니다.
앞서 C++의 구조체에 대해 배웠습니다. C++의 구조체에서는 함수를 선언하고 정의할 수 있었습니다. 그리고 C++의 구조체는 지금부터 배울 '클래스'의 일종이라고 볼 수 있다는 것도 알게 되었습니다. 그렇다면 클래스란 무엇이고, 또 C++의 구조체와 클래스가 다른 점은 무엇일까요?
C++의 구조체는 struct 키워드를 사용했지만, 클래스는 다음과 같이 class키워드를 사용합니다.
class Car
{
int fuelGauge;
int curSpeed;
char gameID[20];
void ShowCarState();
void Accel();
void Break();
}
그리고 구조체 변수는 가능했으나, 클래스 변수를 선언할 때는 다음과 같은 초기화가 불가능합니다.
Car run99 = {100, 0, "run99"}; //구조체는 가능하나, 클래스는 불가능한 초기화
Car run99; //클래스 변수는 초기화가 불가능하므로 변수 선언만
클래스는 기본적으로 클래스 내에 선언된 변수는 클래스 내에 선언된 함수를 통해서만 접근이 가능합니다. 따라서 외부에서 클래스 내부의 변수에 접근하는 초기화가 불가능하게 됩니다. 물론 클래스 변수를 먼저 선언한 후, 다음과 같이 초기화를 시도하는 것도 불가능합니다.
int main(void)
{
Car run99;
run99.fuelGauge = 100;
run99.curSpeed = 0;
strcpy(run99.gameID, "run99");
return 0;
}
이대로면 클래스 내부의 함수를 통하지 않고는 클래스 내부의 변수에 접근할 방법이 없어 보입니다. 정말로 그렇다면 클래스를 제대로 활용할 수 없게 될 것입니다.
접근 제어 지시자
클래스 내부의 함수를 통하지 않고, 클래스 내부의 변수와 함수에 접근하려면 '접근제어 지시자'가 필요합니다. 접근제어 지시자는 총 세 가지가 존재합니다.
public //어디서든 접근 허용
protected //상속관계에 놓여있을 때, 유도 클래스에서의 접근 허용
private //클래스 내(클래스 내에 정의된 함수)에서만 접근 허용
이 중 pretected의 설명에서 '상속관계'라고 하는 것이 보입니다. 상속에 대해서는 나중에 다루게 되니 우선은 다음 예제를 통해 public과 private에 대해서만 알아보겠습니다.
#include <iostream>
#include <cstring>
using std::cout;
using std::cin;
using std::endl;
namespace CAR_CONST
{
enum
{
ID_LEN = 20,
MAX_SPD = 200,
FUEL_STEP = 2,
ACC_STEP = 10,
BRK_STEP = 10
};
}
class Car
{
private:
int fuelGauge; //연료량
int curSpeed; //현재속도
char gamerID[CAR_CONST::ID_LEN]; //소유자 ID
public:
void InitMembers(const char* ID, int fuel);
void ShowCarState();
void Accel();
void Break();
};
void Car::InitMembers(const char* ID, int fuel)
{
fuelGauge = fuel;
curSpeed = 0;
strcpy(gamerID, ID);
}
void Car::ShowCarState()
{
cout << "소유자ID : " << gamerID << endl;
cout << "연료량 : " << fuelGauge << "%" << endl;
cout << "현재속도 : " << curSpeed << "km/h" << endl << endl;
}
void Car::Accel()
{
if (fuelGauge <= 0)
{
return;
}
else
{
fuelGauge -= CAR_CONST::FUEL_STEP;
}
if (curSpeed + CAR_CONST::ACC_STEP >= CAR_CONST::MAX_SPD)
{
curSpeed = CAR_CONST::MAX_SPD;
return;
}
curSpeed += CAR_CONST::ACC_STEP;
}
void Car::Break()
{
if (curSpeed < CAR_CONST::BRK_STEP)
{
curSpeed = 0;
return;
}
curSpeed -= CAR_CONST::BRK_STEP;
}
int main(void)
{
Car run99;
run99.InitMembers("run99", 100);
run99.Accel();
run99.Accel();
run99.ShowCarState();
run99.Break();
run99.ShowCarState();
return 0;
}
/*
실행결과
소유자ID : run99
연료량 : 96%
현재속도 : 20km/h
소유자ID : run99
연료량 : 96%
현재속도 : 10km/h
*/
클래스의 선언 부분을 살펴보겠습니다.
class Car
{
private:
int fuelGauge; //연료량
int curSpeed; //현재속도
char gamerID[CAR_CONST::ID_LEN]; //소유자 ID
public:
void InitMembers(const char* ID, int fuel);
void ShowCarState();
void Accel();
void Break();
};
private: 밑에 세 개의 변수들이 선언되어 있고, public: 밑에 네 개의 함수들이 선언되어 있습니다.
private은 해당 클래스 내의 함수를 통해서만 접근이 가능하도록 허용합니다. 따라서 세 개의 변수들은 클래스 외부에서 접근할 수 없습니다. 이 변수들을 초기화하기 위해 InitMembers 함수가 선언되었습니다.
public은 클래스 외부 어디에서도 접근이 가능하도록 허용합니다. 따라서 클래스 외부에서 네 개의 함수를 호출할 수 있습니다.
만약 private, public, protected 세 개 키워드 중 어느 하나도 사용하지 않고 변수나 함수를 선언할 경우, 자동으로 private으로 선언됩니다.
이쯤 되면 궁금할 수도 있습니다. 그냥 모든 변수나 함수를 public으로 선언해서 접근하기 쉽게 만들면 될 텐데 왜 굳이 private를 사용할까요? 이는 '정보은닉'과 관련한 내용으로 다음 장에서 다루게 됩니다.
객체
지금까지 구조체 변수, 클래스 변수라는 표현을 사용해왔지만 사실 이런 용어는 어울리지 않습니다. 왜냐하면 구조체와 클래스는 단순히 변수의 성격만을 지니는 것이 아니기 때문입니다. 그래서 이젠 변수라는 표현을 대신해서 '객체(Object)'라는 표현을 사용합니다. 그리고 구조체나 클래스 내부에 선언된, 변수를 '멤버변수', 함수를 '멤버 함수'라고 표현합니다.
클래스의 선언과 정의 분리
어떠한 프로그램이건 하나의 파일에 모든 것을 담지는 않습니다.
특히 C++은 클래스 별로 헤더 파일과 소스파일을 생성해서 클래스의 선언과 정의를 분리합니다.
클래스 Car를 대상으로 파일을 나눌 때는 보통 다음과 같이 파일을 구분합니다.
//Car.h
//클래스의 선언을 담는다.
#ifndef CAR_H
#define CAR_H
namespace CAR_CONST
{
enum
{
ID_LEN = 20,
MAX_SPD = 200,
FUEL_STEP = 2,
ACC_STEP = 10,
BRK_STEP = 10
};
}
class Car
{
private:
int fuelGauge; //연료량
int curSpeed; //현재속도
char gamerID[CAR_CONST::ID_LEN]; //소유자 ID
public:
void InitMembers(const char* ID, int fuel);
void ShowCarState();
void Accel();
void Break();
};
#endif
//Car.cpp
//클래스의 정의(멤버함수의 정의)를 담는다.
#include <iostream>
#include <cstring>
#include "Car.h"
using std::cout;
using std::cin;
using std::endl;
void Car::InitMembers(const char* ID, int fuel)
{
fuelGauge = fuel;
curSpeed = 0;
strcpy(gamerID, ID);
}
void Car::ShowCarState()
{
cout << "소유자ID : " << gamerID << endl;
cout << "연료량 : " << fuelGauge << "%" << endl;
cout << "현재속도 : " << curSpeed << "km/h" << endl << endl;
}
void Car::Accel()
{
if (fuelGauge <= 0)
{
return;
}
else
{
fuelGauge -= CAR_CONST::FUEL_STEP;
}
if (curSpeed + CAR_CONST::ACC_STEP >= CAR_CONST::MAX_SPD)
{
curSpeed = CAR_CONST::MAX_SPD;
return;
}
curSpeed += CAR_CONST::ACC_STEP;
}
void Car::Break()
{
if (curSpeed < CAR_CONST::BRK_STEP)
{
curSpeed = 0;
return;
}
curSpeed -= CAR_CONST::BRK_STEP;
}
'공부 일지 > CPP 공부 일지' 카테고리의 다른 글
C++ | 좋은 클래스의 조건, 정보은닉과 캡슐화 (0) | 2021.08.01 |
---|---|
C++ | 객체지향 프로그래밍의 이해 (0) | 2021.08.01 |
C++ | C++에서의 구조체 (0) | 2021.08.01 |
C++ | C++에서 C언어의 표준함수 호출하기 (0) | 2021.08.01 |
C++ | new & delete (0) | 2021.08.01 |