학습 일자 : 2023.03.30
미리 정해진 동작을 수행하는 코드 묶음
어떤 처리를 미리 함수로 만들어 두면 다시 반복적으로 사용 가능
<aside> 💡 함수의 기본 형태 (접근 제한자) [리턴형] [함수 이름] (매개변수) { … return (value); //리턴형이 void가 아닌 경우 무조건 반환 값이 필요함. }
</aside>
접근 제한자 → 생략 가능함. 생략할 경우 기본 값은 private임.
→ 접근 제한자에 대한 자세한 설명은 객체지향으로 넘어가면서 다루도록 함.
일단은 이런 게 있다…. 정도만 알고 넘어가도록!
리턴형
→ 함수의 결과에 대한 데이터의 자료형을 정의함.
→ 반환 값이 없을 경우, void형을 사용함. (void = 반환 값 없음)
→ void가 리턴형을 정의한 경우, 함수가 끝나기 전까지 반드시 return으로 반환형에 맞는
데이터를 return 해야함
* void는 보통 반환 값보다 함수의 행동이 더 중요한 경우에 사용함.
→ 함수 진행 중 return을 만나면, 그 즉시 데이터를 반환하고 함수가 종료 됨.
(이후 문장은 진행되지 않음)
함수이름
→ 함수의 이름은 함수의 행동이 예측 가능하도록 만들어야 함.
매개변수
→ 함수에 추가(입력)할 데이터의 자료형과 변수명
→ 같은 함수에서도 매개변수 입력이 다름에 따라 다른 처리가 가능함
→ 매개변수에 값을 넣어줄 때는 정의한 자료형과 동일한 자료형만 넣어줘야 함
[함수 호출 예제]
internal class Function
{
public void StudyFunction()
{
//반복된 작업 간소화 - 반환형 있음
Console.WriteLine($"가한 데미지는 {TrueDamage(100, 1.2f, 12)}"); //함수호출
Console.WriteLine($"가한 데미지는 {TrueDamage(100, 2.5f, 12)}");
//반복된 작업 간소화 - 반환형 없음
MakeFood("밀가루");
MakeFood("버터");
MakeFood("우유");
int val = ChkReturnFunc1(); //val = 10, ∵ChkReturnFunc1가 10을 반환하기 때문
ChkReturnFunc2();
//메개변수에 따라 결과 값이 달라짐
Console.WriteLine($"ADD : {Add(10, 20)}"); //ADD : 30
Console.WriteLine($"ADD : {Add(100, 200)}"); //ADD : 300
//Console.WriteLine($"ADD : {Add(.2f, 3.2f)}"); //오류. 매개변수는 자료형 맞춰야함
}
void Func1() { } //리턴값과 매개변수가 없는 함수 형태 + 접근제한자 생략
int Func2(int a, int b) { return a + b; } //리턴값과 매개변수가 있는 형태
//매개변수로 ap, buff, ammor을 받고, float로 반환을 하는 TrueDamage함수 정의
float TrueDamage(int ap, float buff, int ammor)
{
float result;
result = (ap * buff) - ammor;
return result;
}
//매개변수 food를 받고, 값을 반환하지 않는 MakeFood함수 정의
void MakeFood(string food)
{
Console.WriteLine($"\\n{food} 뚜껑열어!!!!!!");
Console.WriteLine($"{food} 투입!!!!!!!!!!");
Console.WriteLine($"{food} 뚜껑닫아!!!!!!\\n");
}
//함수 리턴 : 자료형
int ChkReturnFunc1()
{
Console.WriteLine("RETURN 전");
return 10; //10을 리턴하고, 함수를 종료함.
Console.WriteLine("RETURN 후"); //return에서 함수가 완료되므로 실행되지 않음
}
//함수 리턴 : void
void ChkReturnFunc2()
{
Console.WriteLine("RETURN 전");
return;
Console.WriteLine("RETURN 후");
//void는 리턴이 필요하지 않지만, 그래도 return을 만나면 함수가 종료되기 때문에 수행되지 않음.
}
int Add(int a, int b)
{
return a + b;
}
}
함수는 호출되었을 때 해당 함수 블록으로 제어가 전송되며 완료되었을 때 원위치로 전송됨 (원위치 전송을 위해 함수 호출 당시 리턴 주소를 가지고 있음)
→ 함수 호출 당시 필요한 매개변수와 지역변수 크기 할당 + 리턴 주소를 할당함.
이를 관리하기 위해 호출스택을 활용됨.
함수가 순환 구조로 무한히 호출되어 더 이상 스택에 빈 공간이 없는 경우 StackOverflow가 발생
void Main()
{
Func3();
}
//호출 순서
// : (1)→(2)→(7)→(8)→(9)→(4)→(5)→(6)→(10)→(3)
void Func3()
{ // (1)
Func3_2(); // (2)
} // (3)
void Func3_1()
{ // (4)
Console.WriteLine("Func3_1"); // (5)
//Func3(); //무한히 호출되다가 StackOverFlow오류 발생 됨.
} // (6)
void Func3_2()
{ // (7)
Console.WriteLine("Func3_2"); // (8)
Func3_1(); // (9)
} // (10)
<stack 구조>
함수의 매개변수 구성을 달리해서 같은 이름의 함수를 재정의하는 기술
→ 매개변수의 구성을 달리하는 게 중요한 포인트임.
매개 변수 구성은 같고, 리턴 타입만 다른 경우에는 같은 함수로 인식해서 오류 남.
함수의 확장성을 지원하기 위한 기술임.