C++ 복습

열혈 C++ 복습 3

Captic 2019. 11. 19. 17:00

♨ 개인적 해석이 들어간 글임으로, 인지하지 못한 오류가 있을 수 있습니다

교재 - <윤성우 열혈 C++ 프로그래밍>

 

▣ C++에서의 구조체

 - 구조체의 등장배경

 연관 있는 데이터를 하나로 묶어서 프로그램의 구현/관리를 용이하게 하기 위해

  -> 구조체 = 연관있는 데이터를 묶을 수 있는 문법적 장치

  cf) 소프트웨어 = 데이터의 표현 + 데이터의 처리

 

 - C++에서의 구조체 변수 선언

 C언어에서 구조체 변수 : struct Car basicCar; ( Car라는 이름의 구조체, 그 구조체 변수 basicCar)

 -> struct를 넣어 자료형이 구조체를 기반으로 정의되어있음을 알려줘야 한다

     struct를 생략하고 싶다면 별도의 typedef 선언을 추가해야 한다

 

=> C++에서는 별도의 typedef 선언없이 구조체 변수를 선언할 수 있다

 예) Car basicCar;

 

구조체 Car에 대한 내용
구조체 Car를 매개변수로 하는 함수들
main함수와  실행결과

함수 = 데이터의 처리를 담당하는 도구

∴ 데이터와 함께 부류를 형성한다

-> ShowCarState / Accel / Break

    이 3가지 함수는 구조체 Car와 함께 부류를 형성하여, Car와 관련된 데이터의 처리를 담당하는 함수

 ∴ 이 함수들은 Car에 종속적이다

 

그러나! 전역함수이기 때문에 Car 종속적인 성격을 보여주지 못하고 다른 영역에서 함수를 호출하는 것도 가능한 상황

-> C++에서는 구조체 안에 함수 선언/정의가 가능하다

 

 - 구조체 안에 enum 상수의 선언

 

 앞서 나온 코드에서 나온 매크로 상수(예- #define ID_LEN)는 구조체 Car에만 의미있는 상수

 -> 다른 곳에서 사용되지 않으니, Car에 종속적인 함수처럼 구조체 내에 포함되어 있는 것이 좋다

     이때 열거형 enum을 이용

- 이름공간(namespace)을 사용하여 상수가 사용되는 영역을 표시할 수도 있다

 - 구조체 내에 정의된 함수의 길이가 너무 길다면

 -> 함수의 선언만 구조체 내에 해주고, 정의를 구조체 밖에서 해줄 수 있다

     그러면 구조체 내에 존재하는 함수가 한눈에 보인다(구조체 분석에 편하다)

※ 구조체 안에 함수가 정의되어 있으면 인라인 처리가 된다!

-> 하지만 위와 같이 구조체 밖으로 함수의 정의부를 빼면 그 의미가 사라지므로

    필요하다면 명시적으로 인라인 처리를 지시해야한다

 예)

 

 

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

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

이 둘의 코드상 차이는 키워드를 struct로 적느냐 와 class로 적느냐 뿐이다

-> 그러나 class 변수는 구조체 변수처럼 초기화하지 못한다

  ∴  Car run99 = { "run99", 100, 0 }이 struct면? (O)

                                                 class면?   (X)

 

 -> 클래스는 별도의 선언이 없다면, 클래스 내부에 선언된 변수는 클래스 내부에 선언된 함수에서만 접근이 가능하다

 ∴ 클래스를 정의하는 과정에서 접근 허용범위를 선언해주어야 한다

 

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

 C++의 접근제어 지시자 : public / protected / private

  public : 어디서든 접근 허용

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

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

 

위의 구조체로 된 코드를 접근제어 지시자를 포함한 클래스로 변경하면

이외의 함수 부분은 구조체와 동일
실행 결과 역시 구조체와 동일

-> 정리

  1. 접근제어 지시자 A가 선언되면, 그 이후에 등장하는 변수/함수는 A에 해당하는 범위 내에서 접근이 가능하다

  2. 새로운 접근제어 지시자 B가 선언되면, 그 이후로 등장하는 변수/함수는 B에 영향을 받는다

  3. 함수의 정의가 밖에 있더라도, 함수의 선언부가 클래스 내에 있기 때문에 클레스의 일부로 본다

   -> 클래스 내부로 인정되기 때문에 함수 내에서 private 변수/함수에 접근이 가능하다

  4. 구조체는 별도의 접근제어 지시자가 없다면, 그 내에 있는 모든 변수/함수는 public으로 선언된다

  5. 클래스는 별도의 접근제어 지시자가 없다면, 그 내에 있는 모든 변수/함수는 private으로 선언된다

  6. 접근제어 지시자는 세미콜론( ; )이 아닌 콜론( : )이 붙는데, 이는 접근제어 지시자가 특정 위치정보를 알리는

     레이블(라벨)이기 때문이다 + switch문의 case도 레이블이기에 : 이 붙는다

 

 

- 객체(Object), 멤버변수, 멤버함수

 멤버변수 : 클래스 내에 선언되어, 클래스를 구성하는 변수

 멤버함수 : 클래스 내에 선언되어, 클래스를 구성하는 함수

예) 이전에 나온 Car 클래스에서 멤버변수 = char gameID[CAR_CONST::ID_LEN] / int fuelGauge / int curSpeed

                                         멤버함수 = void InitMembers(char * ID,  int fuel) / void ShowCarstate() /

                                                        void Accel() / void Break()

 

- C++에서의 파일분할

 Car.h    : 클래스의 선언을 담는다

  -> 클래스의 선언 = 클래스에 대한 정보, 클래스를 구성하는 외형적인 틀 (선언과 다른부분 = 오류)

Car.h (클래스의 선언부, 헤더파일)

 Car.cpp : 클래스의 정의(멤버함수의 정의)를 담는다

 -> 정의부는 다른 문장의 컴파일에 필요한 정보를 갖지 않기 때문에

    컴파일 된 후 링커에 의해 하나의 실행파일로 묶이기만 하면 된다

이하 내용은 이전과 동일하다

 main함수 부분

 

 - 인라인함수는 헤더파일에 있어야 한다

 인라인 함수는 컴파일 과정에서 "함수의 호출 문이 있는 곳에 함수의 몸체 부분이 삽입되어야" 하기 때문에

 인라인 함수는 정의부까지 헤더파일에 있어야 한다

 

예)

inline 키워드만 추가하고 그대로 컴파일 하면 main에서 함수에 대한 에러를 낸다

-> 에러를 수정하려면 선언과 함께 정의를 헤더파일에서 해주면 된다

까-알-끔 하게 실행된다

 

 

 

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

 - 객체지향 프로그래밍 = 객체(Object, 현실에 존재하는 사물과 대상)와

                                  그 객체의 행동을 실체화 시키는 형태의 프로그래밍

   예) 나는 과일장수에게 두 개의 사과를 구매했다

    -> 나/ 과일장수 / 사과 : 모두 가 객체

 

 -  객체를 이루는 것은 데이터와 기능이다

 -> 과일 장수의 행동 : 과일의 판매

  과일의 판매를 중점에 두고 과일 장수라는 객체를 프로그램화 하면

   1. 과일장수는 과일을 판다

   2. 과일장수는 사과 10개, 오랜지 10개를 보유하고 있다

   3. 과일장수가 보유한 현금은 50,000원이다

-> 1   = 과일장수의 행동

   2, 3 = 과일장수의 상태

 

∴ 객체 = 하나 이상의 상태 정보(데이터) + 하나 이상의 행동(기능)

   -> 상태 정보는 변수로 / 행동은 함수로 표현된다

 

이를 토대로 2번을 변수로 표현하면

 보유한 사과의 수 : int numOfApples

 보유한 오랜지 수 : int numOfOranges

 보유한 현금        : int CurMoney

 

1번을 함수로 표현한다면

 

 

- 과일장수 객체의 정의와 멤버변수의 상수화

 과일장수 클래스의 정의(헤더파일) = 과일장수 객체의 틀

 -> 과일장수의 상태나 행동을 추가하려면 틀에 추가

예)

-> 이때 사과의 판매가격을 일정하게 유지하고자 한다

    그러나 상수화는 선언과 동시에 초기화를 해야하나, 클래스의 멤버변수 선언시 초기화까지 하는 것이 불가능하다

 

 

 - 나(과일구매자)를 표현하는 클래스 정의

 FruitBuyer에게 필요한 상태와 행동은 소유금, 소유한 과일 수, 구매 행위 등이 있다

상태(변수)
행동(함수)

 

- 클래스 기반의 두 가지 객체 생성 방법

객체 생성 없이(이전의 표현으론 클래스 변수) 클래스 내부의 함수나 변수에 접근할 수 없다

-> 클래스의 실체화 = 클래스의 객체화하여야 한다

예) Car car;                          // 일반적인 변수 선언 방식

    Car * ptrCar = new Car;     // 동적 할당 방식(힙 할당 방식)

-> 일반화하기

  일반적 변수 선언 : 클래스이름 변수이름;

  동적 할당 방식 : 클래스이름 * 변수이름 = new 클래스이름;

 

- 앞서 나온 과일가계에서의 예시(판매자/구매자)를 합쳐 완성하기

 

FruitSeller, FruitBuyer 클래스는 이전에 나온것과 동일하다

- 객체간 대화 방법(Message Passing)

하나의 객체가 다른 하나의 객체와 소통하는 방법은 함수호출을 기반으로 한다

예) 나(Buyer)가 과일장수(Seller)에게 소통하기 위해서

    Buyer 내부의 BuyApples함수와 그 매개변수로 쓰인 객체(seller)를 이용하였다

   -> 함수를 이용해 객체와 접근하였다!

 

둘 이상의 객체간의 소통을 위한 함수호출을 '메시지 전달(Message Passing)'이라고 한다

 

 

 

 

연습문제

더보기

▣ 3-1 구조체 내에 함수정의하기

2차원 평면상에서의 좌표를 표현할 수 있는 구조체를 다음과 같이 정의하였다

struct Point

{

   int xpos;

   int ypos;

};

 

위의 구조체를 기반으로 다음의 함수를 정의하고자 한다 (자세한 기능은 실행의 예를 통해서 확인한다)

- void MovePos(int x, int y);            : 점의 좌표이동

- void AddPoint(const Point &pos);  : 점의 좌표증가

- void ShowPosition();                    : 현재 x, y 좌표정보 출력

 

단, 위의 함수들을 구조체 안에 정의를 해서 다음의 형태로 main 함수를 구성할 수 있어야 한다

int main(void)

{

  Point pos1 = { 12, 4 };

  Point pos2 = { 20, 30 };

 

  pos1.MovePos(-7, 10);

  pos1 ShowPosition();   // [5, 14] 출력

 

  pos1.AddPoint(pos2);

  pos1.ShowPostion();    // [25, 44] 출력

 

  return 0;

}

 

▣ 3-2 클래스의 정의

1. 계산기 기능의 Calculator 클래스를 정의하라

 - 기본기능 : 덧셈, 뺄셈, 곱셉, 나누셈

 - 연산시 어떤 연산을 몇번 했는지 기록

 - 단 멤버변수는 private으로, 멤버함수는 public으로 선언

 - main 함수 예시

   int main (void)

{

   Calculator cal;

   cal.Init();

   cout << "3.2 + 2.4 = " << cal.Add(3.2 2.4) << endl;

   cal.ShowOpCount();

   return 0;

}

 

2. 문자열 정보를 내부에 저장하면 Printer라는 이름의 클래스를 디자인하라

 - 클래스의 두 가지 기능은 문자열 저장 / 문자열 출력

   int main (void)

{

   Print pnt;

   pnt.SetString("Hello world!);

   pnt.ShowString();

 

   return 0;

}