반응형
다음 글과 같이 프로그래밍을 하다보면 .h 헤더파일에 클래스 선언부, cpp파일에 클래스 구현부가 들어가야 한다.
평소에는 문제 없이 동작하던 코드가 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파일에 전역변수로 선언 및 초기화 해주도록 하자.
초기화를 하지 않는다면 원하는 결과를 얻지 못할 수도 있다.
반응형
'C++ Programming' 카테고리의 다른 글
[C++ Programming] Template을 사용한 Doubly Linked List 구현 (1) | 2024.03.17 |
---|---|
[C++] MFC에서 CString 사용 시 printf 값이 이상할 경우 해결 방법 (0) | 2023.10.31 |
[C++] visual studio와 maria db 연동 후 값 읽어오기 (0) | 2023.10.25 |
프로그램 실행 시 메모리 구조 (0) | 2023.10.25 |
[C++] 바람직한 C++ 프로그래밍 방법 (0) | 2023.10.24 |