C++에서의 구조체
c++에서는 구조체 변수 선언시,
struct 키워드의 생략을 위한 typedef 선언 불필요
c의 구조체 변수 초기화 c++에서 구조체 변수 초기화
struct Car basicCar; Car basicCar
#include <iostream>
using namespace std;
#define ID_LEN 20
#define MAX_SPD 200
#define FUEL_STEP 2
#define ACC_STEP 10
#define BRK_STEP 10
struct Car
{
char gamerID[ID_LEN]; // 소유자ID
int fuelGauge; // 연료량
int curSpeed; // 현재속도
};
void ShowCarState(const Car &car)
{
cout << "소유자ID: " << car.gamerID << endl;
cout << "연료량: " << car.fuelGauge << "%" << endl;
cout << "현재속도: " << car.curSpeed << "km/s" << endl << endl;
}
void Accel(Car &car)
{
if (car.fuelGauge <= 0)
return;
else
car.fuelGauge -= FUEL_STEP;
if (car.curSpeed + ACC_STEP >= MAX_SPD)
{
car.curSpeed = MAX_SPD;
return;
}
car.curSpeed += ACC_STEP;
}
void Break(Car &car)
{
if (car.curSpeed < BRK_STEP)
{
car.curSpeed = 0;
return;
}
car.curSpeed -= BRK_STEP;
}
int main(void)
{
Car run99 = { "run99", 100, 0 };
Accel(run99);
Accel(run99);
ShowCarState(run99);
Break(run99);
ShowCarState(run99);
Car sped77 = { "sped77", 100, 0 };
Accel(sped77);
Break(sped77);
ShowCarState(sped77);
return 0;
} |
Output :
소유자ID: run99
연료량: 96%
현재속도: 20km/s
소유자ID: run99
연료량: 96%
현재속도: 10km/s
소유자ID: sped77
연료량: 98%
현재속도: 0km/s
바로 위 예제의 함수들은 구조체 Car에 종속적인 함수들이지만 전역함수의 형태를 띠고 있다.
따라서 다른 영역에서 이 함수를 호출하는 실수를 할 수도 있기 때문에 연관된 함수를 하나의 데이터형으로 묶을 필요성이 있다.
c++에서는 구조체 안에 함수 삽입 가능
위의 예제에서 Car에 종속적인 함수들을 구조체 안에 함께 묶을 수도 있다.
#include <iostream>
using namespace std;
#define ID_LEN 20
#define MAX_SPD 200
#define FUEL_STEP 2
#define ACC_STEP 10
#define BRK_STEP 10
struct Car // 함수를 멤버로 지니는 구조체
{
char gamerID[ID_LEN]; // 소유자ID
int fuelGauge; // 연료량
int curSpeed; // 현재속도
void ShowCarState()
{
cout << "소유자ID: " << gamerID << endl;
cout << "연료량: " << fuelGauge << "%" << endl;
cout << "현재속도: " << curSpeed << "km/s" << endl << endl;
}
void Accel()
{
if (fuelGauge <= 0)
return;
else
fuelGauge -= FUEL_STEP;
if (curSpeed + ACC_STEP >= MAX_SPD)
{
curSpeed = MAX_SPD;
return;
}
curSpeed += ACC_STEP;
}
void Break()
{
if (curSpeed<BRK_STEP)
{
curSpeed = 0;
return;
}
curSpeed -= BRK_STEP;
}
};
int main(void)
{
Car run99 = { "run99", 100, 0 }; // 초기화의 대상은 변수
run99.Accel(); // 구조체 내에 선언된 변수에 접근하듯이 함수 호출
run99.Accel();
run99.ShowCarState();
run99.Break();
run99.ShowCarState();
Car sped77 = { "sped77", 100, 0 };
sped77.Accel();
sped77.Break();
sped77.ShowCarState();
return 0;
} |
Output은 동일
구조체안에 enum 상수의 선언
#define ID_LEN 20
( ...)
위의 예제에서는 매크로 상수들이 존재하는데 이들 상수는 구조체 Car에게만 의미가 있는 상수들이기에, 상황에 따라 구조체 내에 포함시키는 것이 좋을수도 있다.
이러한 경우에는 구조체안에 열거형 enum 상수를 선언할 수 있다.
struct Car
{
enum
{
ID_LEN = 20,
MAX_SPD =200,
FUEL_STEP =2
};
char gamerID[ID_LEN];
( ...)
}
혹은 하나의 namespace에 enum 상수의 선언을 하기도 한다.
namespace CAR_CONST
{
enum
{
ID_LEN = 20,
MAX_SPD =200,
FUEL_STEP =2
};
}
구조체 안에는 함수의 선언을 넣고, 함수의 정의는 외부로 뺄수도 있다.
//구조체 안에 삽입된 함수의 선언
struct Car
{
. . . .
void ShowCarState();
void Accel();
. . . .
};
//구조체 외부에 선언된 함수의 정의
void Car::ShowCarState()
{
. . . .
}
void Car::Accel()
{
. . . .
}
구조체 안에 함수가 정의되어 있으면, inline 선언된 것으로 간주
함수의 정의가 구조체 외부에 있을 때, inline 처리를 하기를 바란다면
다음과 같이 명시적으로 inline 선언을 하기도 한다.
inline 함수 -> http://smart2016.tistory.com/88
inline void Car::Break() { . . . . }
클래스와 구조체의 차이점
키워드 struct 를 대신해 class를 사용했을 때, 외형적 차이는 별반 다를게 없어 보인다.
하지만 단순히 키워드만 class로 바꾼다면 선언된 멤버의 접근이 불가능해진다. class안에 아무런 선언이 없을 때 private로 간주
class에는 멤버에 대한 접근 제어 지시자를 통해 접근하어야 한다.
접근 제어 지시자
private
클래스의 내부에서만 접근가능.
public
클래스의 내부/외부 모든 곳에서 접근 가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Car { private: char gamerID[CAR_CONST::ID_LEN]; int fuelGauge; int curSpeed; public: void InitMembers(char * ID, int fuel); void ShowCarState(); void Accel(); void Break(); }; void Car::InitMembers(char * ID, int fuel) { strncpy_s(gamerID, ID, sizeof(CAR_CONST::ID_LEN)); fuelGauge=fuel; curSpeed=0; }; | cs |
객체, 멤버 변수와 멤버 함수
위에서 Car class를 대상으로 생성된 변수를
'객체(object)'라고 한다.
위에서 Car 클래스내에 선언된 변수를 가리켜
'멤버 변수'라고 한다.
위에서 Car 클래스내에 정의된 함수를 가리켜
'멤버 함수'라고 한다.
struct(구조체) 와 class(클래스)는 동일흔히 구조체는 클래스 이전에 선언되고 주로 여러종류의 기억공간을 선언하기 위한 형태로만 보는 경우가 일반적인데, 이는 틀린 생각이다. 구조체 역시 클래스와 동일하게 생성자와 소멸자를 지정할 수 있고, 코딩이 가능하며 내부호출과 캡슐화가 가능하다. 따라서, 하나의 물체(Object) 를 하나의 구조체(struct) 로 선언하고 사용할 수 있다. 따라서, 구조체 내에서도 모든 함수와 명령을 클래스와 동일하게 사용 가능하다. 다만, 멤버에 대해 접근 지정자를 써 주지 않는 경우 구조체는 public이 되고, 클래스는 private이 된다는 차이가 있다.
C++에서의 일반적인 파일 분할
클래스의 선언은 헤더파일에 삽입
클래스의 멤버 함수의 정의는 소스파일
Car.h
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 | #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: char gamerID[20]; int fuelGauge; int curSpeed; public: void InitMembers(char * ID, int fuel); void ShowCarState(); void Accel(); void Break(); }; #endif | cs |
Car.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 | #include <iostream> #include <cstring> #include "Car.h" using namespace std; void Car::InitMembers(char * ID, int fuel) { strcpy(gamerID, ID); fuelGauge=fuel; curSpeed=0; }; void Car::ShowCarState() { cout<<"소유자ID: "<<gamerID<<endl; cout<<"연료량: "<<fuelGauge<<"%"<<endl; cout<<"현재속도: "<<curSpeed<<"km/s"<<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; } | cs |
RacingMain.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include "Car.h" int main(void) { Car run99; run99.InitMembers("run99", 100); run99.Accel(); run99.Accel(); run99.Accel(); run99.ShowCarState(); run99.Break(); run99.ShowCarState(); return 0; } | cs |
다만, inline함수는 컴파일 과정에서 함수의 몸체 부분이 함수 호출 문장으로 대체되기 때문에 다음과 같이 헤더파일에 함께 정의되어야 한다.
CarInline.h
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 | #ifndef __CARINLINE_H__ #define __CARINLINE_H__ #include <iostream> using namespace std; namespace CAR_CONST { enum { ID_LEN =20, MAX_SPD =200, FUEL_STEP =2, ACC_STEP =10, BRK_STEP =10 }; } class Car { private: char gamerID[CAR_CONST::ID_LEN]; int fuelGauge; int curSpeed; public: void InitMembers(char * ID, int fuel); void ShowCarState(); void Accel(); void Break(); }; inline void Car::ShowCarState() { cout<<"소유자ID: "<<gamerID<<endl; cout<<"연료량: "<<fuelGauge<<"%"<<endl; cout<<"현재속도: "<<curSpeed<<"km/s"<<endl<<endl; } inline void Car::Break() { if(curSpeed<CAR_CONST::BRK_STEP) { curSpeed=0; return; } curSpeed-=CAR_CONST::BRK_STEP; } #endif | cs |
CarInline.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 | #include <cstring> #include "CarInline.h" using namespace std; void Car::InitMembers(char * ID, int fuel) { strcpy(gamerID, ID); fuelGauge=fuel; curSpeed=0; }; 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; } | cs |
main은 동일
'코스웨어 > 16년 스마트컨트롤러' 카테고리의 다른 글
2016-09-27_조재찬_스터디일지_CPP-객체 배열과 this포인터, Self-Ref. (0) | 2016.09.27 |
---|---|
2016-09-26_조재찬_스터디일지_CPP-생성자와 소멸자 (0) | 2016.09.26 |
2016-09-25_조재찬_스터디일지_CPP-정보은닉, const함수, 캡슐화 (0) | 2016.09.25 |
2016-09-23_조재찬_스터디일지_CPP-OOP (객체지향 프로그래밍) (0) | 2016.09.23 |
2016-09-21_조재찬_스터디일지_C++기초 3 (bool, reference, new&delete, C 표준함수 호출) (0) | 2016.09.21 |
2016-09-20_조재찬_스터디일지_C++기초 2 (기초예제, inline함수, namespace) (0) | 2016.09.20 |
2016-09-12_조재찬_스터디일지_C언어-이진 트리의 구현과 순회(Traversal) (0) | 2016.09.13 |
2016-09-11_조재찬_스터디일지_C언어-Binary Tree (0) | 2016.09.12 |