728x90

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

 클래스의 내부에서만 접근가능.


 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은 동일



'Study > C++' 카테고리의 다른 글

생성자와 소멸자, 클래스  (0) 2016.09.26
class  (0) 2016.09.25
CPP-Object Oriented Programming (객체지향 프로그래밍)  (0) 2016.09.23
c++ 기초3  (0) 2016.09.21
c++ 기초  (0) 2016.09.19

+ Recent posts