본문 바로가기
C++ Programming

[C++ Debugging] LNK1120, LNK2001 에러(Static 사용 시)

by TYB 2023. 10. 24.
반응형

다음 글과 같이 프로그래밍을 하다보면 .h 헤더파일에 클래스 선언부, cpp파일에 클래스 구현부가 들어가야 한다.

 

[C++] 바람직한 C++ 프로그래밍 방법

간략하게 설명하자면 객체 지향 프로그램 답게 짜야한다는 것인데, 클래스 헤더.h, 클래스 구현부.cpp, main.cpp로 나뉘어야 한다. 여러 클래스가 있다면 클래스의 헤더와 구현부도 클래스의 갯수에

program-developers-story.tistory.com

 

평소에는 문제 없이 동작하던 코드가 static 멤버 변수를 쓰려고 할 때 발생한다.

 

아래 코드 처럼 cafe.h에 static 선언 후 cpp파일에  함수를 구현하고 main문에 넣어 동작시켰다.

static 관련 함수 45,46번 라인

//cafe.h
#pragma once
#ifndef CAFE_H
#define CAFE_H

#include <iostream>
#include <string>
#pragma warning(disable:4996)
#define MENU 12

using namespace std;


class Cafe_Menu
{
private:
	string coffee;
	string size;
	int price;

public:
	Cafe_Menu();
	~Cafe_Menu();
	string get_menu_coffee(void);
	string get_menu_size(void);
	int get_menu_price(void);
	void insert_menu(string coffee, string size, int price);
};


class Cafe
{
private:
	string coffee;
	string size;
	int price;

public:
	Cafe();
	~Cafe();
	void enter_menu(string coffee, string size, int price);
	void display_menu(int index);
	void display_menu(int index, int order_count);
	int get_price(void);
	static int total_price; // 공금
	static void get_total_price(int input);
	
};




#endif

static 관련 함수 87번 라인

//cafe.cpp

#include "cafe.h"

//===============Cafe_Menu Class


Cafe_Menu::Cafe_Menu()
{
	coffee.clear();//string clear strlen=0
	size.clear();
	price = 0;
}


Cafe_Menu::~Cafe_Menu()
{

}

string Cafe_Menu::get_menu_coffee(void)
{
	return this->coffee;
}

string Cafe_Menu::get_menu_size(void)
{
	return this->size;
}


int Cafe_Menu::get_menu_price(void)
{
	return this->price;
}

void Cafe_Menu::insert_menu(string coffee, string size, int price)
{
	this->coffee = coffee;
	this->size = size;
	this->price = price;
}


//====================Cafe Class

//int Cafe::total_price = 0;


Cafe::Cafe()
{
	this->coffee.clear();//string clear strlen=0
	this->size.clear();
	this->price = 0;
}

Cafe::~Cafe()
{

}

void Cafe::enter_menu(string coffee, string size, int price)
{
	this->coffee = coffee;
	this->size = size;
	this->price = price;
}

void Cafe::display_menu(int index)
{
	std::cout << "[" << index + 1 << "] " << coffee<<" " << size<< " " << ((double)price / 1000) << "\n";

}

void Cafe::display_menu(int index,int order_count)
{
	std::cout << "[" << index + 1 << "] " << coffee << " " << size << " " << order_count << "개\n";

}


int Cafe::get_price(void)
{
	return this->price;
}

void Cafe::get_total_price(int input) {
	total_price += input;
}

 

 

static 관련 함수 87번 라인

//==========main.cpp

#include "cafe.h"

int main(void)
{
	//---object
	Cafe_Menu Coffee_Menu[12];
	Cafe coffee[12];
	//variables
	int order= 0;
	int order_count[12] = { 0 };
	char input[100];
	int i = 0;
	int day_total = 0, total = 0;
	char* ptr;
	
	//coffee_menu 객체 입력
	Coffee_Menu[0].insert_menu("카페_아메리카노", "Short", 3600);
	Coffee_Menu[1].insert_menu("카페_아메리카노", "Tall", 4100);
	Coffee_Menu[2].insert_menu("카페_라떼", "Short", 4100);
	Coffee_Menu[3].insert_menu("카페_라떼", "Tall", 4600);
	Coffee_Menu[4].insert_menu("카푸치노", "Short", 4100);
	Coffee_Menu[5].insert_menu("카푸치노", "Tall", 4600);
	Coffee_Menu[6].insert_menu("카페모카", "Short", 4100);
	Coffee_Menu[7].insert_menu("카페모카", "Tall", 4600);
	Coffee_Menu[8].insert_menu("카라멜_마키아또", "Short", 5100);
	Coffee_Menu[9].insert_menu("카라멜_마키아또", "Tall", 5600);
	Coffee_Menu[10].insert_menu("스타벅스_돌체_라떼", "Short", 5100);
	Coffee_Menu[11].insert_menu("스타벅스_돌체_라떼", "Tall", 5600);



	for (i = 0; i < MENU; i++)//0~11 //12번 루프하면서 coffee_menu 객체 값들을 읽어옴
	{
		coffee[i].enter_menu(Coffee_Menu[i].get_menu_coffee(), Coffee_Menu[i].get_menu_size(), Coffee_Menu[i].get_menu_price());
	}


	//display
	for (i = 0; i < MENU; i++)//0~11 //12번 루프
	{
		coffee[i].display_menu(i);
	}


	//static으로 바꿀만한게 total과 day_total
	while(1)
	{
		cout << "\n주문할 상품의 번호를 입력하세요(ex: 1 11 2 3 5): ";
		cin.getline(input, 100, '\n');
		cout << "\n주문한 상품:"<<endl;
		i = 0, total=0;
		
		//get input and parsing
		ptr = strtok(input, " ");
		while (ptr != NULL)               // 자른 문자열이 나오지 않을 때까지 반복
		{
			cout << stoi(ptr) << endl;// 자른 문자열 출력
			order = stoi(ptr);
			if (order == 0)
			{
				cout << "\n==============매출 통계=============== " << endl;
				for (i = 0; i < 12; i++)
				{
					if (order_count[i] > 0)
					{
						coffee[i-1].display_menu(i-1, order_count[i]);
					}
				}
				cout << "\n매출액 총계: " << coffee[0].total_price <<endl;
				return 0;
			}
			else if (order > 0 && order < 12)//0~11사이에 정상적 입력이라면
			{
				total += coffee[order-1].get_price();
				order_count[order]++;
				coffee[order-1].display_menu(order-1);
			}

			else 
			{
				cout << order <<"는 없는 메뉴입니다." << endl;
			}
			ptr = strtok(NULL, " ");      // 다음 문자열을 잘라서 포인터를 반환
		}
		coffee[0].get_total_price(total);

	}
}

동작시키면 LNK1120, LNK2001 에러가 발생했다고 오류코드가 나온다.

 

해결방법으로 static으로 선언해줬었던 static int total price;를 초기화 해줘야한다.

cafe.cpp파일이나 main.cpp 파일에 전역변수로 int Cafe::total_price = 0; 을 선언해주고 다시 코드를 실행시키면 정상적으로 동작한다.

 

위와 같은 에러가 발생하는 이유는 static의 메모리 저장 시점과 관련이 있다.

 

static은 프로그램이 시작할 때 오직 하나만 생성되어 프로그램 종료 시까지 정적으로 사용된다. 

하지만 헤더파일에서 클래스 안에 선언만 해놓고 구현 및 초기화를 하지 않으니, 프로그램 시작 시 해당 변수를 찾을 수 없어 확인 할 수 없는 외부 참조라고 나오는 것이다.

 

따라서 static을 사용할 때는 반드시 해당 값을 cpp파일에 전역변수로 선언 및 초기화 해주도록 하자.

초기화를 하지 않는다면 원하는 결과를 얻지 못할 수도 있다.

반응형