Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

메모장

열혈 C++ 복습 1 본문

C++ 복습

열혈 C++ 복습 1

Captic 2019. 11. 17. 00:13

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

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

 

1강 - C언어 기반의 C++ 1

 

▣ printf/scanf를 대신하는 입출력 : " std::cout / std::cin "

- HelloWorld 입출력

 1. 헤더파일 선언문 : " #include <iostream> "

   - C언어에서 printf와 scnaf를 이용하기 위해서 추가했던 <stdio>와 동일한 역할

   - istream은 stdio와 동일한 헤더파일이지만, 프로그래머(사용자)가 직접 정의한 헤더파일이 아닌.

     표준 헤더파일이기 때문에 선언시 " --.h "가 붙지 않는다

     -> 표준 헤더파일은 생략하기로 약속

 

 2. " std::cout " 과 " << "을 이용한 출력

  - std::cout << 출력하고픈_내용;

   -> c언어의 printf("%서식문자", 출력대상)과 같은 역할을 하지만,

       c언어때 처럼 서식문자(예- 정수 = %d / 문자열 = %s), 포멧이 필요하지 않다

 - " << "도 실은 연산자이다

  -> 2개 이상의 출력대상을 연이어 출력할 수 있다

    예) 상단의 코드에서 7행 ( std::cout << "Hello" << "World!" << std::endl; )

         Hellow 출력후 World! 출력후 std::endl로 마무리(출력)

 

 3. " std::endl " 을 이용한 개행

  - " << " 연산자를 이용한 std::endl의 출력은 개행(줄바꾸기)을 의미한다

 

 

- scanf를 대신하는 데이터의 입력

 -> 사용자에게 2개의 수를 입력받고, 입력 받은 숫자의 덧셈 결과를 출력하는 예시

 1. " std::cin "과 " >> " 연산자

  - std::cin >> 저장할_변수

   -> cout때와 동일하게 cin도 별도의 포멧 지정이 필요없다.

     -> 위의 코드를 int -> double로 바꾸더라도 진행에는 문제가 없다

 

2. 지역변수의 선언

 - C언어는 지역 변수 선언이 항상 제일 먼저 왔어야 했다.

 - C++의 지역변수 선언은 함수 내 어디든 삽입이 가능하다

  예) 위 코드의 9, 13행

 

 

▣ 두 개의 정수를 입력 받아서 그 사이에 존재하는 정수들의 합을 계산하는 코드

- 8행 ( std::cin >> val1 >> val2; )

 -> 연속적인 데이터 입력 가능, 데이터 간 구분은 스페이스바/ Enter / Tab 모두 가능

  예) Enter 키를 이용한 구분

 

- 12행, 17행 (for문)

 -> for문 안에서 변수 선언 및 사용 가능 / but for문 내에서 선언한 변수를 for문 외부에서 사용 불가

 

▣ 배열 기반의 문자열 입출력 예시

 

함수 오버로딩 (Function Overloading)

▣ 함수 오버로딩의 이해

- C언어에서 함수의 인자만 다르고 이름이 같은 경우는 있을 수 없다

 예) int MyFunc(int num){~~}  // int MyFunc(int a, int b){~~} ->컴파일 오류

 

- C++에서는 위 두 함수를 다른 것으로 인식 한다

 -> 함수 호출 시 전달되는 인자를 통해서 호출하고자 하는 함수의 구분이 가능하기 때문

∴ 매개변수의 선언형태가 다르다면, 동일한 이름의 함수정의가 가능하다

   이러한 형태(동일한 이름, 매개변수에서 차이)의 함수정의를 가르켜 '함수 오버로딩(Function Overloading)'이라 한다

더보기

이전 C에서 인자와 매개변수를 구분없이 쓴거 같아 다시 정리된 글을 찾았다

출처: https://skmagic.tistory.com/104

 

매개변수(Parameter) - 함수 선언시

인자(Argument) - 함수 호출시

지금 이해하면 이런 식인 것 같은데 더 공부를 해보자

이전 C에서 인자와 매개변수를 구분없이 쓴거 같아 다시 정리된 글을 찾았다

출처: https://skmagic.tistory.com/104

 

매개변수(Parameter) - 함수 선언시

인자(Argument) - 함수 호출시

 

지금 이해하면 이런 식인 것 같은데 더 공부를 해보자

 

- C와 C++이 차이나는 이유

 -> C++은 호출할 함수를 찾을 때, 함수의 이름 + 매개변수의 선언 이 두 가지 정보를 동시에 활용

     반면 C는 함수의 이름만 활용 = 함수 오버로딩 불가

 

- 함수 오버로딩의 기준

 -> 함수의 오버로딩이 가능하려면 매개변수의 선언이 달라야 한다 / 반환형이 다르면 불가

 예) int MyFunc(float A) {~}

      int MyFunc(char*B) {~}

    -> 매개변수의 자료형이 다르므로 함수 오버로딩 가능

      int MyFunc(int C) {~}

      int* MyFunc(int D) {~}

    -> 반환형이 다르기 때문에 함수 오버로딩 불가

 

 

- 함수 오버로딩 예

 

매개변수의 디폴트 값 (Default Value)

▣ 매개변수에 설정하는 '디폴트 값'의 의미

- 디폴트 값 = 기본적으로 설정되어 있는 값

- 함수 호출시 다른 인자를 전달되지 않으면 해당 함수의 매개변수 값으로 정해놓은 값을 인자로 사용하겠다

 예)

∴ MyFuncOne() = MyFuncOne(7)

   MyFuncTwo() = MyFuncTwo(5) = MyFuncTwo(5, 7)

   -> 인자가 1개만 오더라도, 2번째 인자가 전달된 것이 없으므로 디폴트 값이 전달된다

 

- 함수의 원형을 별도로 선언하는 경우, 매개변수의 디폴트 값은 함수의 선언에만 위치시켜야 한다

예)

 

- 부분적 디폴트 값 설정

매개변수가 여러개 있는 함수 중에서 일부의 매개변수만 디폴트 값을 설정할 수 있다

-> 함수에 인자가 왼쪽에서부터 채워지기 때문에, 가장 오른쪽 매개변수의 디폴트 값부터 설정할 수 있다

예) 기본 함수: int ABC(int a, int b, int c, int d) {~}

                   int ABC(int a, int b = 1, int c = 2, int d =3) {~} -> 가능

                     => ABC(2, 3);  //  ABC(2, 3, 2, 3);

                          ABC(1);     //  ABC(1, 1, 2, 3);

                          ABC();      //  컴파일 에러 = int a에는 디폴트 값이 없으므로 적어도 1개의 인자가 필요하다

                   int ABC(int a = 1, int b, int c, int d = 1) {~} -> 불가능

                     => int a가 int b/c 보다 먼저 디폴트 값을 가질 수 없다

                   

 

▣ 인라인(inline) 함수

- in(내부) + line(프로그램 코드라인) = 프로그램 코드라인 안으로 들어가 버린 함수

 

- 매크로 함수의 장/단점

 장점: 일반적인 함수에 비해 실행속도가 빠르다

 단점: 정의하기 어렵고, 복잡한 함수를 매크로의 형태로 정의하는데 한계가 있다

 

예)

위와 같이 함수의 몸체부분이 함수의 호출문을 완전히 대체 했을 때 '함수가 인라인화 되었다'라고 표현

 

- C++ 기반의 인라인 함수 정의

매크로의 장점(처리속도)을 살리면서 단점(정의하기 어렵다)을 보안하는 것이 C++의 인라인 함수

 매크로 함수의 인라인화 -> 전처리기가 처리

 inline키워드를 이용한 함수의 인라인화 -> 컴파일러가 처리

  ∴ 컴파일러가 함수의 인라인화로 성능이 저하된다고 판단할 경우 inline 키워드 무시할 수도

     반대로 일부 함수를 인라인 처리 하기도 한다

 

- 매크로 함수에는 있지만, 인라인 함수에 없는 장점

-> 매크로는 자료형에 구애받지 않는다(인라인 함수는 함수의 정의와 동일하기에 자료형이 정해진다)

이를 함수의 오버로딩으로 해결할 수도 있으나 그럼 인라인화를 왜하냐

∴ 이때 필요한 것이 template

 

 

▣ 이름공간(namespace)에 대한 소개

 - 이름공간 : 특정 영역에 이름을 붙여주기 위한 문법적 요소

 - 다른 사람들끼리 하나의 프로젝트를 만들때 함수의 이름이 겹치는 등 상호간 구분이 되지 않는 문제가 생기는 경우

   각자의 이름공간을 두어 거기에 함수를 선언하고 호출시에 특정 이름공간의 특정 함수를 불러오게 한다

 

뭔소린지 모를땐 예시)

이러면 누가 만든 함수가 실행되느냐 문제가 생긴다
각각의 namespace를 만들고 호출시 각각의 namespace에 딸려 있는 함수를 호출

 

- " :: " 범위지정 연산자 : 이름공간을 지정할 때 사용한다

 

- 이름공간 기반의 함수 선언과 정의 구분

함수 선언부 및 main함수
각 이름구역에 있는 함수 정의
코드 실행 결과

 

- 이름공간의 중첩

같은 num 이지만 각각의 namespace에 따라 다르게 저장이 되어있기에 다른 결과 값이 나왔다

 

- cout / cin / endl 역시 std라는 namespace 안에 선언되어 있는 것

 

- using을 이용한 이름공간의 명시

 using 이름공간::함수이름or변수이름

예)

-> using의 위치가 main안에 있으므로, 지역변수처럼 사용된다 (main을 벗어나면 효과X)

∴ using 선언을 함수 밖에, 전역의 형태로 하면 전역변수처럼 어디서든 효과를 볼 수 있다.

 

- using namespace std

 -> 이름공간 std에 선언된 모든 것에 대해 이름공간 지정의 생략 가능

 

- 이름공간 별칭 지정

 -> 이름공간이 중첩되면서까지 과도하게 사용될 경우

AAA::BBB::CCC에 ABC라는 별칭을 붙여 사용

 

- 범위지정 연산자의 또 다른 기능

 지역변수와 전역변수의 이름과 같을 경우, 지역변수 우선 이때 전역 변수를 사용하고 싶다면

 -> 전역 변수 앞에 :: 붙이면 쌉가능

예)

 

 

 

연습문제

더보기

▣ 1-1 C++ 기반의 데이터 입출력 연습문제

 - 1.  사용자로부터 5개의 정수를 입력 받아서, 그 합을 출력하는 프로그램 작성 (입력은 단계적으로 진행)

정답>>

 

 

 

 

 - 2. 프로그램 사용자로부터 이름과 전화번호를 문자열의 형태로 입력 받아서,

      입력받은 데이터를 그대로 출력하는 프로그램 작성

정답>>

 

 

 

 

 

 

 

 

 - 3. 숫자를 하나 입력 받아서 그 숫자에 해당하는 구구단을 출력하는 프로그램 작성

정답>>

 

 

 

 

 - 4. 

정답>>

 

 

 

 

 

▣ 1-2 함수 오버로딩 문제

다음 main 함수에서 필요로 하는 swap 함수를 오버로딩 해서 구현하라

 

int main(void)

{

  int num1 = 20, num2 = 30;

  swap(&num1, &num2);

  std::cout << num1 << ' ' << num2 << std::endl;

 

  char ch1 = 'A', ch2 = 'Z';

  swap(&ch1, &ch2);

  std::cout << ch1 << ' ' << ch2 << std::endl;

 

  double dbl1 = 1.111, dbl2 = 5.555;

  swap(&dbl1, &dbl2);

  std::cout << dbl1 << ' ' << dbl2 <<std::endl;

  return 0;

}

 

void swap(int* a, int* b)

{

  int temp;

  temp = *a;

  *a = *b;

  *b = temp;

}

void swap(int* a, int* b)

{

  int temp;

  temp = *a;

  *a = *b;

  *b = temp;

}

▣ 1-3 매개변수의 디폴트 값

1. 

#include  
int BoxVolume(int length, int width = 1, int height = 1); 

int main(void) 
{ 
  std::cout << "[3, 3, 3] : " << BoxVolume(3, 3, 3) << std::endl; 
  std::cout << "[5, 5, D] : " << BoxVolume(5, 5) << std::endl; 
  std::cout << "[7, D, D] : " << BoxVolume(7) << std::endl; 
  //std::cout << "[D, D, D] : " << BoxVolume(3, 3, 3) << std::endl; 

  return 0; 
} 

int BoxVolume(int length, int width, int height) 
{ 
   return length * width * height; 
} 

 

함수 BoxVolume를 '매개변수의 디폴트 값 지정' 형태가 아닌, '함수 오버로딩'의 형태로 재구현하라

main는 변경하지 않고, 실행결과도 동일해야 한다

 

 

 

2. 다음 함수 오버로딩의 문제점을 찾고, 그 이유를 설명하시오

int SimpleFunc(int a = 10)

{

 return a + 1;

}

 

int SimpleFunc(void)

{

 return 10;

}

 

 

▣ 1-4 파일의 분할

C++을 제대로 공부하려면 필요한 내용

1. 헤더파일의 의미와 정의 방법

2. 헤더파일에 삽입할 내용과 소스파일에 삽입할 내용을 구분하는 방법

3. 둘 이상의 헤더파일과 소스파일을 만들어서 하나의 실행파일로 컴파일 하는 방법

 

위의 내용을 기반으로 아래의 코드를 헤더/소스1/소스2파일로 분할하라

 

#include  

namespace BestComImpl 
{ 
  void SimpleFunc(void); 
}

namespace ProgComImpl 
{ 
  void SimpleFunc(void); 
}

int main(void) 
{ 
  BestComImpl::SimpleFunc();

  ProgComImpl::SimpleFunc(); 
}

void BestComImpl::SimpleFunc(void)
{ 
  std::cout << "BestCom이 정의한 함수" << std::endl; 
  ProgComImpl::SimpleFunc();
}

void ProgComImpl::SimpleFunc(void) 
{ 
  std::cout << "ProgCom이 정의한 함수" << std::endl; 
}

 

 

 

 

 

 

'C++ 복습' 카테고리의 다른 글

열혈 C++ 복습 4  (0) 2019.11.22
열혈 C++ 복습 3  (0) 2019.11.19
열혈 C++ 복습 2  (0) 2019.11.17
C++ 복습 1  (0) 2019.08.04