본문 바로가기
UNITY/유니티게임스쿨

[유니티게임스쿨 TIL] C# 기초 문법 이해 :: 재귀 함수, 연산자, 클래스와 인터페이스

by 램플릿 2024. 5. 30.

 

오늘의 공부


전역 변수와 지역 변수

○ static : 전역적인 데이터임을 의미하는 키워드로, 전역 변수나 전역 함수를 지정한다.

static 함수 안에서는 클래스 함수 또는 다른 static 함수를 호출할 수 있다.

 

○ 지역 변수는 변수가 선언된 스코프 안에서만 생명주기가 유지된다.

 

 

배열

  int[] array = {1,2,3,4,5,6}

  = 연속적인 메모리공간(정수형) 6개가 나열된 array라는 이름의 데이터묶음.

 

재귀함수

함수 내에서 자기 자신을 다시 호출하는 함수.

 

(+멘토님 부가설명)

"재귀(recursive) 함수는 '현대의' 일반적인 프로그래밍에서 잘 쓰이지 않습니다.
재귀 함수가 에러 발생을 많이 시켜요.

분기처리를 제대로하지 않으면 무한으로 돌 수도 있고 메모리 초과(stackoverflow) 에러도 발생시킬 수 있어요.

가독성 측면에서는 최악입니다.
재귀함수의 사용은 주로 알고리즘(트리형식 데이터구조 탐색 정도)말고는 사용 안해본 것 같아요"

//배열의 전 요소를 더한 값을 반환하는 SumArray 재귀함수
static int SumArray(int[] array, int length) { 
    
    if(length==0)        
        return 0;
    else 
        return array[length-1]+SumArray(array, length-1);

}

static void Main(string[] args)
{
    int[] array = { 1, 2, 3, 4, 5, 6 };
    Console.WriteLine(SumArray(array, array.Length));
}

결과 :: 21

 

 

피보나치 수열 만들기 (재귀함수 연습문제)

 static int Fibonacci(int num) {
     if (num <= 2)
     {
         return 1;
     }
     else
     {
         return Fibonacci(num - 1) + Fibonacci(num - 2);
     }
 }

 static void Main(string[] args)
 {
     for (int i = 1; i <= 10; i++)
     {
         Console.WriteLine(i+"번째 피보나치 수열 : "+Fibonacci(i));
     }
     
     Console.ReadKey();
 }

 

Tip👍 :: 추천사이트
C#Study : C# 개념+예제 https://www.csharpstudy.com/

 

 

연산자와 연산자 우선순위

 

사칙 연산

  • +  :덧셈
  • -  :뺄셈
  • *  :곱셈
  • /  :나눗셈
  • %  :나머지

 

비교 연산 ( True or False로 리턴 )

  • ==  :같은지 비교
  • !=  :같지 않은지 비교
  • >, <, >=, <=  :대소 비교

 

논리 연산

  • &&  :AND
  • ||  :OR
  • !  :NOT

 

비트 논리 연산

  • &  :bit AND
  • |  :bit OR
  • ^  :bit XOR
  • ~  :bit COMPLEMENT
  • <<  :bit LEFT SHIFT
  • >>  :bit RIGHT SHIFT
//비트 논리 연산
// 5 = 00000101
// 4 = 00000100

Console.WriteLine(5 & 4); // 두 비트가 모두 1이면 1
// 00000100 (=4)

Console.WriteLine(5 | 4); // 두 비트중 하나라도 1이면 1
// 00000101 (=5) 

Console.WriteLine(5 ^ 4); // 두 비트를 비교해서 비트가 서로 다르면 1
// 00000001 (=1)

Console.WriteLine(~5);
// 00000101 → 11111010 (= -6)으로 바뀜 (맨 앞은 부호비트이므로 부호도 바뀜)

Console.WriteLine(3 << 3); // 3를 왼쪽으로 3번 쉬프트(2^3배 곱해지는 효과)
// 00000011 → 00011000 =16

 

할당 연산

  • =  :할당 연산자
  • +=  :덧셈할당
  • -=  :뺄셈할당
  • *=  :곱셈할당
  • /=  :나눗셈할당
  • %=  :나머지할당
  • &=  :AND할당
  • |=  : OR...
  • ^=  : XOR...
  • <<=  : LSHIFT...
  • >>=  : RSHIFT...

 

 

class와 struct의 차이

     C#에서 클래스는 할당연산 시 참조를 하지만 struct 는 복사를 한다.

public struct Cat //구조체
{
    public string name;
    public int age;

    public void PrintMyInfo()
    {
        Console.WriteLine("name : " + name + " age : " + age);
    }
}

public class Dog //클래스
{
    public string name;
    public int age;

    public void PrintMyInfo()
    {
        Console.WriteLine("name : " + name + " age : " + age);
    }
}

internal class Program
{
    static void Function1(int k)
    {
        for (int i = k; i < 10; i++)
        {
            Console.WriteLine(i);
        }
    }

    static void Main(string[] args)
    {
        Dog a = new Dog();
        a.name = "멍멍이";
        a.age = 1;

        a.PrintMyInfo();

        Dog b = new Dog();
        b.name = "깡깡이";
        b.age = 3;

        b.PrintMyInfo();

        Dog c = a;
        c.PrintMyInfo();

        a.name = "셜록이";
        c.PrintMyInfo();
		//a.PrintMyInfo(); 해도 똑같은 결과 출력됨.
		//이유 : c가 a를 참조하기 때문에 c의 변경이 a에 그대로 영향을 주기 때문.

        //////////////////strcut///////////////////////


        Cat d = new Cat();

        d.name = "야옹이";
        d.age = 5;

        Cat e = d;
        d.name = "곱슬이";
        e.PrintMyInfo();
		
        d.PrintMyInfo();
		//e에는 참조가 아닌 복사가 이루어지므로 이후 d를 변경해도 e에 영향없음.
    }
}
💡질문 :: struct도 상속이 가능한가요?
struct는 상속이 불가능하다. 또한 struct 정의 시 변수를 미리 초기화 할 수 없다. (C#10.0버전 이후로 가능)

 

 

클래스 상속과 다형성 : 오버라이드

클래스의 상속

  • 부모 클래스를 상속받으면 부모가 가진 변수, 함수를 참조하여 똑같이 이용할 수 있다.

다형성

  • 오버라이드는 부모에게서 상속받은 같은 이름의 함수를 자식 클래스에 맞게 바꾸어 쓰는 것이다.
  • virtual 키워드가 붙은 가상함수는 이를 상속받은 자식 클래스에서 override 해서 사용 가능하다.
  • 가상 함수가 추상(abstract)와 다른점은 가상함수는 필요에 따라 재정의 하면 되지만 추상함수는 이를 상속받은 클래스에서 필.수.적으로 오버라이드 해야한다는 것이다. (참고자료 : https://velog.io/@cedongne/C-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4-vs-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4 )

 

부모 virtual public void PrintMyInfo() => 자식 override public void PrintMyInfo()

💡 질문 :: virtual이 붙은 함수만 오버라이딩 할 수 있나요?
⇒ 함수명 앞에 new를 사용하면 재정의(오버라이딩이 아닌 덮어쓰기 형식)방법으로 함수를 바꾸어 쓸 수 있다.
new는 기존 부모의 함수를 새롭게 선언하는 키워드이다.

부모 public void NewFunction() => 자식 new public void NewFunction()

 

 

다운캐스팅

Animal.newFunction(); // 부모함수 실행

((Cat)Animal).newFunction(); // 자식함수 실행 (명시적 형변환을 통한 다운캐스팅)

 

 

인터페이스 interface

함수들의 정의를 내려주는 상위개념이며 이들을 상속받아 강제로 인터페이스의 함수를 오버라이드하도록 강제하는 것이다. 또한 인터페이스는 객체화 될 수 없다.

🎓새로운 지식
○ 클래스는 여러개의 인터페이스를 상속받을 수 있다. 그러나 다중클래스를 상속받을수는 없다.
○ 인터페이스 정의 시 변수는 선언할 수 없다. (프로퍼티 형식으로 선언할 수 있으나 이는 메모리 할당이 아니고 함수와 같은 방법이다.)

 

 


 

나중에 배울 문법 : delegate, callback, lamda, reflection ..