메모장
열혈 C++ 복습 1 본문
♨ 개인적 해석이 다분한 글임으로, 인지하지 못한 오류가 있을 수 있습니다 ♨
교재 - <윤성우 열혈 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)에 대한 소개
- 이름공간 : 특정 영역에 이름을 붙여주기 위한 문법적 요소
- 다른 사람들끼리 하나의 프로젝트를 만들때 함수의 이름이 겹치는 등 상호간 구분이 되지 않는 문제가 생기는 경우
각자의 이름공간을 두어 거기에 함수를 선언하고 호출시에 특정 이름공간의 특정 함수를 불러오게 한다
뭔소린지 모를땐 예시)
- " :: " 범위지정 연산자 : 이름공간을 지정할 때 사용한다
- 이름공간 기반의 함수 선언과 정의 구분
- 이름공간의 중첩
같은 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 |