본문 바로가기
School Study/2021-2

[week 10] C++ 복습_6장 함수 (2)

by 전전긍긍 2021. 11. 27.

20211104_C++_공부기록

 

  • void 함수 : void 함수는 값을 반환하지 않는 함수이다.
void printGrade(double score)
{
  if (score >= 90.0)
    cout << 'A' << endl;
  else if (score >= 80.0)
    cout << 'B' << endl;
  else if (score >= 70.0)
    cout << 'C' << endl;
  else
    cout << 'F' << endl;
  return; //생략가능
}

int main()
{
  double score;
  cout << "점수를 입력하시오 : ";
  cin >> score;
  cout << "당신의 성적은 : << printGrade(score) << endl;
  return 0;
}

  • 기본인수

매개변수에 대한 기본값을 정의할 수 있다.

void printArea(double radius = 1) //기본 인수
{
  double area = radius * radius * 3.14159;
  cout << "area is " << area << endl;
}

int main()
{
  printArea();  //인수로 1 이 사용됨
  printArea(4);
  return 0;
}

*주의 : 기본인수와 보통인수가 같이 선언될 때, 기본인수는 매개변수 목록의 맨 뒤쪽에 와야 한다.

void t1(int x, int y = 0, int z); //잘못된 경우
void t3(int x, int y = 0, int z = 0); //올바른 경우, 컴파일러가 차례대로 매칭을 하기 때문

t3(1, ,20); //잘못된 호출
t3(1); //y, z 매개변수는 기본값으로 할당됨

  • 함수 오버로딩

함수 이름이 같아도 매개변수 리스트가 달라야 한다 (타입 또는 개수)

#include <iostream>
using namespace std;

int max(int num1, int num2)
{
    if (num1 > num2)
        return num1;
    else
        return num2;
}

double max(double num1, double num2)
{
    if (num1 > num2)
        return num1;
    else
        return num2;
}

char max(char num1, char num2)
{
    if (num1 > num2)
        return num1;
    else
        return num2;
}

int main()
{
    cout << "The max between 3 and 4 is " << max(3, 4) << endl;
    cout << "The max between 3.0 and 5.4 is " << max(3.0, 5.4) << endl;
    cout << "The max between a and f is " << max('a', 'f') << endl;
    return 0;
}
/*
The max between 3 and 4 is 4
The max between 3.0 and 5.4 is 5.4
The max between a and f is f
*/

*반환값유형이 아닌 매개변수의 타입이 달라야 함

//반환값유형만 다르다고 해서 다른 함수로 인식하지 못한다
int max (int, int);
double max (int, int);
//매개변수 타입이 달라야 한다.
int max (int, int);
double max (double, double);

- 모호한 호출

//모호한 호출
int maxNumber(int num1, double num2)
{
  if (num1 > num2)
    return num1;
  else
    return num2;
}
double maxNumber(double num1, int num2)
{
  if (num1 > num2)
    return num1;
  else
    return num2;
}
int main()
{
  cout << maxNumber(1, 2) << endl; //모호한 호출 발생
  return 0;		 //컴파일러가 어떤 함수를 호출할지 결정 못함
}

  • 인라인 함수

함수 호출 -> 오버헤드 (ex. 함수 간의 제어 전달, 인자 복사 등) 발생한다.

오버헤드 줄이기 위해 -> 인라인 함수의 내용을 복사해서 함수 호출자리에 붙인다.

(위 코드와 아래 코드는 동치)

inline void f(int month, int year) 
{
  cout << "month is " << month << endl;
  cout << "year is " << year << endl;
}

int main()
{
  int month = 10, year = 2008;
  f(month, year);  // 인라인 함수 호출
  f(9, 2010); // 인라인 함수 호출
  return 0;
}
int main()
{
  int month = 10, year = 2008;
  cout << "month is " << month << endl; //함수 코드 복사
  cout << "year is " << year << endl;
  cout << "month is " << 9 << endl; //함수 코드 복사
  cout << "year is " << 2010 << endl;
  return 0;
}

* 인라인 함수는 여러 곳에서 호출되는 긴 함수의 경우에는 적합하지 않다.

* 단지 함수를 인라인 함수로 처리해 달라고 컴파일러에게 요구만 하는 것이고 실제 인라인 함수로 처리할지 말지는 컴파일러에게 달려 있다.


  • 변수의 범위 - 전역 변수

전역 변수(global variable) : 모든 함수 외부에서 선언되어 파일 내 모든 함수에서 접근이 가능한 변수

* 기본값이 0으로 설정되어 있다

* 범위 : 변수를 선언한 지점부터 프로그램 끝까지

* 아무 함수에서나 막 써버리거나 남발하면 위험. 필요한 경우가 아니라면 쓰지 않는 것이 좋다.

 

  • 변수의 범위 - 지역 변수

지역 변수(local variable) : 함수 안에서 정의된 변수

* 범위 : 선언한 지점으로부터 그 변수가 포함된 해당 블록의 끝까지 (해당 함수 전체)

* 서로 다른 블록에서 같은 이름의 지역 변수 선언이 가능

* 매개변수는 지역변수라고 볼 수 있다. 

#include <iostream>
using namespace std;

void t1(); //함수 원형
void t2(); //함수 원형

int main() {
	t1();
	t2();
	return 0;
}

int y; //전역변수, 자동으로 0으로 초기화 됨, 전역변수는 ram안에 Heap이란 안전한 공간에 따로 분리

void t1()
{
	int x = 0; //t1 지역변수
	cout << "x is " << x << endl; //0
	cout << "y is " << y << endl; //0
	x++; //1
	y++; //1
}

void t2()
{
	int x = 0; //t2 지역변수
	cout << "x is " << x << endl; //0
	cout << "y is " << y << endl; //1
}

/*
x is 0
y is 0
x is 0
y is 1
*/

  • 변수의 범위(생존기간) - 정적(static) 지역 변수

* 생존기간 : 그 변수가 언제까지 살아있냐

- 함수 실행이 완료되면 모든 지역 변수는 메모리에서 사라지게 되는데, 때로는 변수에 저장된 값을 유지해야 할 때가 있다.

- 정적 지역 변수는 프로그램이 끝날 때까지 메모리에서 사라지지 않고 계속 유지된다.

- stack이 아닌 Heap에 들어간다.

*** 전역변수랑 다른 점은 무엇인가 ? 범위라는 측면에서는 정적 지역 변수는 여전히 지역 변수이기 때문에 전역 변수는 전체 블록이지만 정적 지역 변수는 해당 블록에서만 적용가능

void t1(); // 함수원형 
int main(){
  t1();
  t1(); //y는 부를 때마다 reset되기 때문에 y++해서 1이지만 x는 정적 지역 변수로 선언했기 때문에 계속 ++된다
  return 0;
}

void t1(){
  static int x = 0; //정적 지역변수는 처음 생성될 때 한번만 초기화 됨
  int y = 0;
  x++;
  y++;
  cout << "x is " << x << endl;
  cout << "y is " << y << endl;
}

  • 함수 추상화

- "함수 내용"을 함수에 대한 자세한 구현 사항을 포함하고 있는 블랙박스로 생각하는 것

ex. pow(a,b) 함수를 쓸 때, 지수가 되는 과정(로직)을 우리가 몰라도 컴파일러에서 알아서 계산을 해준다.

여기서 로직이 함수 내용이다. 우리는 함수 헤더에 pow(a,b)만 써도 컴파일러는 자동으로 a**b를 출력한다.

- 함수의 호출자에게 함수의 내용은 감춰지는데 이를 정보은닉 또는 캡슐화라고 한다.

- 함수의 구현내용이 변경되더라도 함수서명만 변경하지 않는다면 프로그램은 영향을 받지 않게 된다.


  • 실습
#include <iostream>
using namespace std;

void p(); //함수원형
void q(); //함수원형
int j = 40; //전역변수

int main()
{
	p(); // i=6, j=6
	p(); // i=6, j=7
	p(); // i=6, j=8
	p(); // i=6, j=8
	q(); // j=40
	return 0;
}
void p()
{
	int i = 5; //지역변수
	static int j = 5; //정적 지역변수
	i++;
	j++;
	cout << " i = " << i << endl; 
	cout << " j = " << j << endl;
}

void q()
{
	cout << " j = " << j << endl;
}
/*
 i = 6
 j = 6
 i = 6
 j = 7
 i = 6
 j = 8
 i = 6
 j = 9
 j = 40
*/