개발/C, C++

[C++] 클래스(Class)와 객체(Object)

huiyu 2018. 12. 15. 14:07

C++의 구조체 : http://huiyu.tistory.com/entry/C-C%EC%97%90%EC%84%9C%EC%9D%98-%EA%B5%AC%EC%A1%B0%EC%B2%B4?category=463903


 - C++의 구조체는 클래스의 일종이다, 그러나 클래스와 구조체는 차이점을 갖고 있다.


- 클래스와 구조체의 차이점

 : 키워드 struct를 대신해서 class를 사용한다면, 구조체가 아닌 클래스가 된다.

 [구조체]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Car
{
  char gamerID[ID_LEN];
  int fuelGaunge;
  int curSpeed;
  void SHowCartState()
  {
    ...
  }
  void Accel()
  {
    ...
  }
  void Break()
  {
    ...
  }
}
 
int main(void)
{
  Car run99 = {"run99"1000};
}
cs

[클래스]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Car
{
  char gamerID[ID_LEN];
  int fuelGaunge;
  int curSpeed;
  void SHowCartState()
  {
    ...
  }
  void Accel()
  {
    ...
  }
  void Break()
  {
    ...
  }
}
 
int main(void)
{
  Car run99;
}
cs

* 구조체 struct를 class로만 바꿔주면 클래스로 선언하게 된다.
그러나 구조체에서의 선언과 같이 Car run99={"run99", 100, 0}의 형태로 초기화가 안된다.
 이유는 클래스 내에 선언된 함수가 아닌, 다른 영역에서 변수를 초기화 하려 했기 때문이다.
 클래스는 기본적으로 (별도의 선언을 하지 않으면) 클래스 내에 선언된 변수는 클래스 내에 선언된 함수에서만 접근 가능하다.
 따라서 아래와 같이 선언해야 된다.

1
2
3
4
5
6
7
int main(void)
{
  Car run99;
  strcpy(run99.gamerID, "run99"); //(x)
  run99.fuelGauge=100//(x)
  run99.curSpeed=0//(x)
}
cs

-> 그러나 4~6번째 줄은 컴파일 되지 않는데, C++에서 클래스는 접근과 관련해서 별도의 선언을 해줘 변수 및 함수의 접근을 허용해줘야 한다.


- 접근제어 지시자(접근제어 레이블)

 C++에서의 접근제어 지시자
 1) public : 어디서든 접근 허용
 2) protected : 상속관계에 놓여있을 때, 유도 클래스에서의 접근 허용
 3) private : 클래스 내에 정의된 함수에서만 접근 허용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Car
{
private:
  char gamerID[ID_LEN];
  int fuelGaunge;
  int curSpeed;
 
public:
  void SHowCartState()
  {
    ...
  }
  void Accel()
  {
    ...
  }
  void Break()
  {
    ...
  }
}
cs

* 키워드 struct를 이용해서 정의한 구조체에 선언된 변수와 함수에 별도의 접근제어 지시자를 선언하지 않으면, 모든 변수와 함수는 public
* 키워드 class를 이용해서 정의한 클래스에 선언된 변수와 함수에 별도의 접근제어 지시자를 선언하지 않으면, 모든 변수와 함수는 private


*용어정리

 - 객체(Object)
  : 구조체 변수, 클래스 변수는 변수의 성격만 지니는 것이 아니다. 그래서 변수를 대신해서 '객체(Object)'라는 표현을 사용한다.
 - 멤버변수
  : 클래스를 구성하는(클래스 내에 선언된) 변수
 - 멤버함수
  : 클래스를 구성하는(클래스 내에 선언된) 함수


* C++에서의 파일분할

- Header(*.h) : 클래스의 선언
  * 클래스의 선언 : 컴파일러가 클래스와 관련된 문장의 오류를 잡아내는데 필요한 최소한의 정보로써, 클래스를 구성하는 외형적인 틀

- (*.cpp) : 클래스의 정의
  * 클래스의 정의 : 함수의 정의, 이는 다른 문장의 컴파일에 필요한 정볼르 갖고 있지 않다. 따라서 함수의 정의는 컴파일 된 후, 링커에 의해 하나의 실행파일로 묶이기만 하면 된다.

[example]

 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
#ifndef __CAR_H__
#define __CAR_H__
 
namespace CAR_CONST
{
  enum
  {
    ID_LEN=20,
    MAX_SPEED=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();
};
 
#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
44
45
#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
    fuel-=CAR_CONST::FUEL_STEP;
 
  if((curSpped+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
15
#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

 ** 인라인 함수는 헤더파일에 넣어야 한다.
 -> 인라인 함수는 컴파일 과정에서 함수의 호출문이 있는 곳에 함수의 몸체 부분이 삽입된다.
 때문에 인라인 함수는 클래스의 선언과 동일한 파일에 저장되어서 컴파일러가 동시에 참조할 수 있게 해야한다.

 그래서 위 예제 car.cpp에서 함수를 인라인으로 변경하면 컴파일 에러가 발생한다.

1
2
3
4
5
6
inline void Car::ShowCarState()
{
  cout<<"소유자ID: "<<gamerID<<endl;
  cout<<"연료량: "<<fuelGauge<<"%"<<endl;
  cout<<"현재속도: "<<curSpeed<"km/s"<<endl<<endl;
}
cs

 => 컴파일 에러를 고치기 위해선 car.h에 선언되어야 한다.

* 컴파일러는 파일 단위로 컴파일 한다.  A.cpp와 B.cpp을 동시에 컴파일해서 하나의 실행파일을 만든다 해도,
 A.cpp컴파일 과정에서 B.cpp을 참조하지 않으며, B.cpp컴파일 과정에서 A.cpp을 참조하지 않는다.
 그래서 위 예제에서 클래스 선언부로 옮기는 것과 같이 클래스의 선언과 인라인 함수 정의를 묶어 두어야한다.

 [참고]

윤성우 열혈 C++ 프로그래밍 03-2 클래스(Class)와 객체(Object)

728x90
반응형