• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    해결됨

static 함수 관련 질문

21.02.28 09:05 작성 조회수 274

0

공부를 하던 도중 static함수에 대해 헷갈리는 부분이 생겼습니다.

1. static 변수들은 데이터 영역에 값이 잡히는 것으로 알고 있습니다. 일반 함수들은 코드영역에 값이 잡히구요

그렇다면 static 함수들은 데이터 영역에 있는건가요 아니면 코드 영역에 있는 건가요?

2. c++이랑 다르게 namespace 안에 class들과 static 너무 많아서 헷갈리는 부분이 있습니다. 언제 static이 붙은 함수가 생기고

언제 static을 안 쓰는건지 헷갈립니다.

namespace CSharp_연습용

{

    class Program

    {

        enum ClassType

        {

            None,

            Knight,

            Archer,

            Mage,

        }

        struct Player

        {

            public int hp;

            public int attack;

        }

        enum MonsterType

        {

            None,

            Slime,

            Orc,

            Skeleton,

        }

        struct Monster

        {

            public int hp;

            public int attack;

        }

        static ClassType ChooseClass()

        {

            Console.WriteLine("직업을 선택하세요!");

            Console.WriteLine("[1] 기사");

            Console.WriteLine("[2] 궁수");

            Console.WriteLine("[3] 법사");

            string input = Console.ReadLine();

            ClassType choice = ClassType.None;

            switch (input)

            {

                case "1":

                    choice = ClassType.Knight;

                    break;

                case "2":

                    choice = ClassType.Archer;

                    break;

                case "3":

                    choice = ClassType.Mage;

                    break;

            }

            return choice;

        }

        static void CreatePlayer(ClassType choice, out Player player)

        {

            switch (choice)

            {

                case ClassType.Knight:

                    player.hp = 100;

                    player.attack = 10;

                    break;

                case ClassType.Archer:

                    player.hp = 75;

                    player.attack = 12;

                    break;

                case ClassType.Mage:

                    player.hp = 50;

                    player.attack = 15;

                    break;

                default:

                    player.hp = 0;

                    player.attack = 0;

                    break;

            }

        }

        static void CreateRandomMonster(out Monster monster)

        {

            Random rand = new Random();

            int randMonster = rand.Next(1, 4);

            switch (randMonster)

            {

                case (int)MonsterType.Slime:

                    Console.WriteLine("슬라임이 스폰");

                    monster.hp = 20;

                    monster.attack = 2;

                    break;

                case (int)MonsterType.Orc:

                    Console.WriteLine("오크가 스폰");

                    monster.hp = 40;

                    monster.attack = 4;

                    break;

                case (int)MonsterType.Skeleton:

                    Console.WriteLine("스켈레톤이 스폰");

                    monster.hp = 30;

                    monster.attack = 3;

                    break;

                default:

                    monster.hp = 0;

                    monster.attack = 0;

                    break;

            }

        }

        static void Fight(ref Player player, ref Monster monster)

        {

            while (true)

            {

                monster.hp -= player.attack;

                if (monster.hp <= 0)

                {

                    Console.WriteLine("승리 했습니다");

                    Console.WriteLine($"남은 체력, {player.hp}");

                    break;

                }

                player.hp -= monster.attack;

                if (player.hp <= 0)

                {

                    Console.WriteLine("패배했습니다");

                    break;

                }

            }

        }

        static void EnterField(ref Player player)

        {

            while (true)

            {

                Console.WriteLine("필드에 접속했습니다");

                Monster monster;

                CreateRandomMonster(out monster);

                Console.WriteLine("[1] 전투 모드로 돌입");

                Console.WriteLine("[2] 일정 확률로 마을로 도망");

                string input = Console.ReadLine();

                if (input == "1")

                {

                    Fight(ref player, ref monster);

                }

                else if (input == "2")

                {

                    Random rand = new Random();

                    int randValue = rand.Next(0, 101);

                    if (randValue <= 33)

                    {

                        Console.WriteLine("도망치는데 성공했습니다");

                        break;

                    }

                    else

                    {

                        Fight(ref player, ref monster);

                    }

                }

            }

        }

        static void EnterGame(ref Player player)

        {

            while (true)

            {

                Console.WriteLine("마을에 접속");

                Console.WriteLine("[1] 필드로 간다");

                Console.WriteLine("[2] 로비로 돌아가기");

                Console.WriteLine();

                string input = Console.ReadLine();

                switch (input)

                {

                    case "1":

                        EnterField(ref player);

                        break;

                    case "2":

                        return;

                    default:

                        break;

                }

            }

        }

        static void Main(string[] args)

        {

            while (true)

            {

                ClassType choice = ChooseClass();

                if (choice == ClassType.None)

                    continue;

                Player player;

                CreatePlayer(choice, out player);

                EnterGame(ref player);

            }

        }

    }

    

}

위와 같이 TEXTRPG 코드에서 

3. Main 옆에 왜 static이 붙는건가요?

4. Main을 제외하고 나머지 함수들(CreatePlayer, EnterField등)은 class Program에 소속된 함수인 것 맞나요?

5.  만약 나머지 함수들이 class Program에 소속된 거라면 왜 static을 붙이는 건가요? static 함수들은 클래스에 종속적인 것이지

특정 객체에 종속적인 것이 아닌 것이라고 말씀해주셨습니다. Main이란 함수와 나머지 함수들이 현재 Program이란 클래스에 다 같이 있는 것이니까 나머지 함수에 static이 없어도 Main 안에서 작동해야 하는 것 아닌가요?

6.  질문하면서 떠오른 코드가

        static void Main(string[] args)

        {

            Program p1;

            while (true)

            {

                ClassType choice = ChooseClass();

                if (choice == ClassType.None)

                    continue;

                Player player;

                p1.CreatePlayer(choice, out player);

                EnterGame(ref player);

            }

        }

CreatePlayer 함수에서 static을 제거하고 Program의 객체 p1을 찍어서 p1이 호출한 함수로써 CreatePlayer을 쓰면 되지 않을까 했는데, 할당되지 않은 p1 지역변수를 사용했다는 안내가 나옵니다.  어떤점이 문제인 것인가요?

답변 1

답변을 작성해보세요.

1

1. 코드 영역
C#, Java 같이 자체적으로 메모리 관리가 되는 언어는
C++처럼 그렇게 메모리를 일일히 생각할 필요가 없습니다.
(그리고 실제로 static 변수가 C++과 다르게 heap에 할당되는등, 조금 방식이 다릅니다.)

2. static?
사실 알고보면 C++과 동일한데,
한가지 큰 차이는 C#에서는 C++과 다르게 함수가 class 밖에 홀로 존재할 수 없습니다.
그러니 전역으로 void main() 같은 것은 만들 수 없고
반드시 어떤 클래스에 소속되어 있어야 하는데,
그것이 class Program이라고 보면 됩니다.

3. Main이 왜 static?
main 함수는 딱 1개만 존재해야 하니, static이 붙은 것입니다.
Program p = new Program();
p.Main();
굳이 이렇게 할 이유는 없을 것이고 그래서도 안 됩니다.

4. Main을 제외하고 나머지 함수들(CreatePlayer, EnterField등)은 class Program에 소속된 함수인 것 맞나요?

네 맞습니다.

5.  만약 나머지 함수들이 class Program에 소속된 거라면 왜 static을 붙이는 건가요? static 함수들은 클래스에 종속적인 것이지 특정 객체에 종속적인 것이 아닌 것이라고 말씀해주셨습니다. Main이란 함수와 나머지 함수들이 현재 Program이란 클래스에 다 같이 있는 것이니까 나머지 함수에 static이 없어도 Main 안에서 작동해야 하는 것 아닌가요?

아닙니다. 이건 C++ C# 차이 없는 부분입니다.
static 함수는 특정 클래스 객체 ('Instance')와는 무관하기 때문에,
특정 클래스 객체에 종속적인
(비static) 함수들을 호출할 수 없습니다.
그러니 static 함수에서는 또 다른 static 함수, 혹은 static 변수만 사용할 수 있습니다.
static 함수 내부에서 굳이 비static 함수를 사용하고 싶다면
Program p = new Program(); 과 같이 실제 객체를 1개 만들어서,
새로 만든 객체를 통해서 기능을 사용해야 합니다.

위 예제에서 C# 특성상 Main이 static으로 고정되어 있기 때문에,
편의상 나머지도 static을 붙여 바로 사용하는 것입니다.
static을 제거하면 빌드 에러가 나는 것을 확인해보시기 바랍니다.
static을 다 제거하고 함수를 만들 것이라면
반드시 인스턴스를 만들어서 사용해야 합니다.

답변 감사합니다