[C++] 3.클래스의 기본


C++에서의 구조체



C언어에서 연관있는 데이터를 하나로 묶기 위해서 구조체를 이용했죠??

C++에서도 구조체를 지원하고 있습니다!

//구조체 정의
struct Car
{
	char gamerID[10];
	int speed;
};

//구조체 선언
struct Car car1;



선언시 struct를 생략하기 위해 typedef를 이용하였지만,

C++에서는 typedef를 이용하지 않아도 됩니다!


//기존 C언어
typedef struct Car
{
	char gamerID[10];
	int speed;
}Car;

//C++ typedef 생략가능
struct Car
{
	char gamerID[10];
	int speed;
};

//위와 같이 정의해도 선언 시 struct 생략 가능합니다.

Car car1;



그리고 C++에서는 구조체와 관련된 함수를 삽입할 수도 있습니다!


struct Car
{
	char gamerID[10];
	int speed;
	
	void Show_Car_State(void)
	{
		cout<<"ID: "<<gamerID<<endl;
		cout<<"현재속도: "<<speed<<endl;
	}
}



함수가 구조체 내에 선언되면, 구조체 내에 선언된 변수에 직접접근이 가능합니다~

함수 호출은 다음과 같이 합니다

Car car1={"꾸리",0};

car1.Show_Car_State();



구조체 변수 내에 함수가 각각 별도로 존재하는 것이 아니라,

모든 구조체 변수가 하나의 함수를 공유합니다!

그리고 구조체 내부에 함수의 세부구현이 있으면, 복잡해보일 수가 있습니다.

그래서 다음과 같이 함수의 세부내용을 밖으로 빼낼 수 있습니다.


struct Car
{
	char gamerID[10];
	int speed;
	void Show_Car_State(void); //함수 원형만 선언
}

void Car::Show_Car_State(void) //세부 내용을 밖으로 빼냄 ::연산자를 이용합니다~
{
	cout<<"ID: "<<gamerID<<endl;
	cout<<"현재속도: "<<speed<<endl;
}



다만, 함수 세부내용이 구조체 안에 정의되어 있으면, 함수를 인라인으로 처리합니다!

하지만 위와 같이 구조체 밖으로 빼내면 이러한 의미가 사라집니다.


따라서 인라인의 의미를 그대로 유지하려면,

다음과 같이 inline을 이용해서 인라인 처리를 지시해야합니다.


inline void Car::Show_Car_State(void) //inline 키워드 사용
{
	cout<<"ID: "<<gamerID<<endl;
	cout<<"현재속도: "<<speed<<endl;
}



마지막으로 구조체와 관련된 상수는 namespace로 관리합니다!


//매크로 함수로 정의 된 상수

#define MAX_CAR_SPEED 100 //자동차의 최대 속력
#define MIN_CAR_SPEED 0 //자동차의 최소 속력

//위의 상수는 구조체 Car와만 관련있는 상수이기에 namespace로 따로 관리합니다.

namespace Car_Const
{
	enum
	{
		MAX_CAR_SPEED=100, MIN_CAR_SPEED=0
	};
};

//접근할 때는 ::을 사용합니다~

Car_Const::MAX_CAR_SPEED



클래스(Class)와 객체(Object)



앞서 설명한 C++의 구조체는 클래스의 일종입니다.

구조체와 클래스의 차이는 키워드 struct를 대신해서 class를 사용하면 됩니다~

간단하죠~!?


//클래스 car

class Car
{
	char gamerID[10];
	int speed;
	
	void Show_Car_State(void);
}

//클래스 객체(변수) 선언도 다음과 같이 하면 됩니다

Car car1;



성질은 위의 설명한 구조체와 동일합니다~!

다만 중요한 차이점이 있는데 바로 ‘접근제어 지시자’입니다!


접근 제어 지시자

public		어디서든 접근 허용

protected	상속관계에 놓여있을 때, 유도 클래스에서의 접근 허용

private 	클래스 내(클래스 내에 정의된 함수)에서만 접근 허용



사용방법은 다음과 같습니다.


class Car
{
	private: //클래스 내에서만 접근 허용
		char gamerID[10];
		int speed;
	
	public: //어디서든 접근 허용
		void Show_Car_State(void);
}

//gamerID와 speed는 클래스 내에서만 접근 할 수 있기에

//다음과 같은 선언은 컴파일 오류를 발생시킵니다

int main(void)
{
	Car car1={"꾸리", 0}; (X)

	Car car1;

	strcpy(car1.gamerID, "꾸리"); (X)
	
	//하지만 Show_Car_State는 어디서든 호출 가능합니다.
	
	car1.Show_Car_State(); (O)
}



구조체와 클래스의 차이점은 다음과 같습니다.


키워드 struct를 이용해서 정의한 구조체에 선언된 변수와 함수에

별도의 접근제어 지시자를 선언하지 않으면, 모든 변수와 함수는 public으로 간주됩니다.


키워드 class를 이용해서 정의한 클래스에 선언된 변수와 함수에 

별도의 접근제어 지시자를 선언하지 않으면, 모든 변수와 함수는 private로 간주됩니다.



또한, 함수의 정의를 클래스 밖으로 빼도, 이는 클래스의 일부이기 때문에,

함수 내에서는 private로 선언된 변수에 접근이 가능합니다.

그렇다면 private로 선언 된 변수를 어떻게 외부에서 초기화시킬까요??

클래스 내부에 초기화 함수를 만들어주어야합니다~~


class Car
{
	private: 
		char gamerID[10];
		int speed;
	
	public: 
		void Show_Car_State(void);
		void init_Car(char* id,int sd); //초기화 함수
}

void Car::init_Car(char* id,int sd)
{
	strcpy(gamerID, id);
	speed=sd;
}



용어정리: 객체, 멤버변수, 멤버함수



다음은 클래스와 관련된 용어입니다~~

위의 예제 class Car에서,

Car car1; 이라고 선언이 되었다면,

car1을 바로 객채라고 부릅니다~! (구조체에선 구조체변수에 해당)



그리고 클래스를 구성하는 변수 char gamerID, speed를 

멤버 변수라고하고,

클래스를 구성하는 함수 Show_Car_State, init_Car를

멤버 함수라고 합니다~~



C++에서의 파일분할



어떠한 프로그램이건 하나의 파일에 모든 것을 담지 않습니다.

특히 C++에서는 클래스 별로 헤더파일과 소스파일을 생성해서

클래스의 선언과 정의를 분리하는 경우가 많기 때문에 많은 수의 파일이 만들어집니다.

그러면 헤더파일과 소스파일에 어떤 걸 담는 지 잠깐 간단히 알아보겠습니다.

헤더파일에 담는 내용

1.클래스의 선언
2.함수 선언
3.구조체 선언 및 정의
4.인라인 함수 선언 및 정의 등등



소스파일에 담는 내용

1.클래스의 정의
2.함수 정의 등등



파일의 분할을 연습할 겸 헤더파일과 소스파일로 분리해서

간단한 자동차 프로그램을 작성해보겠습니다!


CarDefine.h



#ifndef __CARDEFINE_H__
#define __CARDEFINE_H__

#include <iostream>
using namespace std;

//자동차와 관련된 상수
namespace CAR_CONST
{
   enum
   {
	      MAX_SPEED=100, MIN_SPEED=0, ADD_SPEED=5, SUB_SPEED=5
   };
};

//클래스 선언
class Car
{
	private: 
		char gamerID[10];
		int speed;
	
	public: 
		void Show_Car_State(void); //상태 출력 함수
		void init_Car(char* id,int sd); //초기화 함수
		void Accel(void); //속도 증가 함수
		void Break(void); //속도 감소 함수
}

//인라인 함수 정의
inline void Car::Show_Car_State(void)
{
	cout<<"ID: "<<gamerID<<endl;
	
	cout<<"현재속도: "<<speed<<endl;
}

#endif




CarDefine.cpp


#include "CarDefine.h"
#include <cstring>
using namespace std; //표준함수들 모두 std에 있으므로

//초기화 함수 정의
void Car::init_Car(char* id,int sd)
{
	strcpy(gamerID,id);
	
	speed=sd;
}

//Accel 함수 정의
void Car::Accel(void)
{
	if(speed>=CAR_CONST::MAX_SPEED)
		return;
	speed+=CAR_CONST::ADD_SPEED;
}

//Break 함수 정의
void Car::Break(void)
{
	if(speed<=CAR_CONST::MIN_SPEED)
		return;
	speed-=CAR_CONST::SUB_SPEED;
}




Main.cpp



#include "CarDefine.h"

int main(void)
{
	Car car1; //객체생성
	car1.init_Car("꾸리",0); //객체 초기화
	car1.Accel(); //속도증가
	car1.Break(); //속도감소
	car1.Show_Car_State(); //상태 출력
	return 0;
}



객체지향 프로그래밍의 이해



클래스 기반의 두 가지 객체 생성 방법이 있습니다~

Car car1; //일반적인 변수의 선언방식

Car *pcar1=new Car; //동적 할당 방식



그리고 다른 객체에 존재하는 함수를 호출할 수도 있습니다~


class Car
{
	private:
	
	...
	
	public:
		
	...
	void check(void)
	{
		driver.state(); //driver라는 다른 객체의 함수를 호출
	}



이것은 마치 객체끼리 대화하는 것처럼 보여서 메시지 전달(Message Passing)이라고 합니다!



객체지향 프로그래밍은 현실에 존재하는 사물과 대상,

그리고 그에 따른 행동을 있는 그대로 실체화 시키는 형태의 프로그래밍이고,

C++ 또한 객체지향 프로그래밍입니다~

절차 지향 언어인 C언어보다 훨씬 우월하고, 편리한 언어이죠!ㅋㅋㅋ

클래스에 대해서 다음 장에서 더 배워보도록 하겠습니다!