본문 바로가기
코스웨어/16년 스마트컨트롤러

2016-09-22_조재찬_스터디일지_CPP-Class

by 알 수 없는 사용자 2016. 9. 23.
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로 간주


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



728x90