c++ 오버라이딩시 헤더파일 분리

조회수 770회

오버라이딩을 받는 3개의 클래스와 1개의 메인 클래스, 메인 함수로 헤더파일을 나누고 싶습니다. 근데 virtual때문인지 헤더파일을 나누는 기준도 잘 모르겠고 어찌저찌 실행은 되는데 모든 virtual함수를 헤더파일에 넣어야만 계산이 됩니다. 혹시 헤더파일을 어떻게 나누어야하는지 알 수 있을까요?

#ifdef virtual
#include <iostream>
using namespace std;

#include "ice1.h"
#include "Icecream.h"

ice1 :: virtual void icecream(int left) { }
ice1 :: virtual void show() { }
ice1 :: virtual void count(int left) { }
ice1 :: virtual int all(int left) { return sum; }


virtual void icecream(int left) {
    if (ice_count >= left) {
        ice_count -= left;
        sell += left;
        sum = sell * price1;
        cout << "구매하였습니다." << endl;
    }
    else
        cout << "개수가 부족하여 구매할 수 없습니다." << endl;
}
virtual void count(int left) {
    if (ice_count >= left || ice_count >= 0) {
        cout << "월드콘의 총 판매 금액 : " << sum << "원" << endl;
        cout << "---------------\n" << endl;
    }
    else {
        cout << "월드콘의 총 판매 금액 : " << sum << "원" << endl;
        cout << "---------------\n";
    }
}
virtual int all(int left) {
    return sum;
}

#endif
#pragma once
#ifndef ICE1_H
#define ICE1_H
#include <string>
#include <iostream>
#include "Icecream.h"

using namespace std;

class ice1 : public Icecream {
    int price1;
public:
    ice1(string in, int ice_c, int price_1) : Icecream(in, ice_c) { price1 = price_1; }
    virtual void show() {
        cout << icename << "의 남은 개수 " << ice_count << "개 " << endl << "              " << icename << "의 가격 " << price1 << "원" << endl;
    }
};

#endif 
#ifdef virtual
#include<iostream>
using namespace std;

#include "Icecream.h"

Icecream :: virtual void icecream(int left) { }
Icecream :: virtual void show() { }
Icecream :: virtual void count(int left) { }
Icecream :: virtual int all(int left) { return sum; }

#endif
#pragma once
#ifndef ICECREAM_H
#define ICECREAM_H
#include <string>
#include <iostream>

using namespace std;

class Icecream {
protected:
    string icename;
    int ice_count, sum = 0, sell = 0;
public:
    Icecream(string in, int ice_c) { icename = in; ice_count = ice_c; }
    virtual void icecream(int left) { }
    virtual void show() { }
    virtual void count(int left) { }
    virtual int all(int left) { return sum; }
};
#endif
#include<iostream>
using namespace std;

#include "ice1.h"
#include "ice2.h"
#include "ice3.h"
#include "Icecream.h"

int main() {
    int ice_num, left;
    string choice;
    Icecream* p[3];
    p[0] = new ice1("월드콘", 10, 1000);
    p[1] = new ice2("와", 10, 1200);
    p[2] = new ice3("돼지바", 10, 700);

    cout << "아이스크림 3개는 다음과 같다. \n";
    cout << "아이스크림1 : "; p[0]->show();
    cout << "아이스크림2 : "; p[1]->show();
    cout << "아이스크림3 : "; p[2]->show();
    cout << endl;

    while (true) {
        cout << "아이스크림(1: 월드콘, 2: 와, 3: 돼지바)와 갯수 입력>>";
        cin >> ice_num >> left;
        if (ice_num == 1) {
            p[ice_num - 1]->icecream(left);
            p[ice_num - 1]->count(left);
            p[0]->show();
            p[1]->show();
            p[2]->show();
        }
        else if (ice_num == 2) {

            p[ice_num - 1]->icecream(left);
            p[ice_num - 1]->count(left);
            p[0]->show();
            p[1]->show();
            p[2]->show();
        }
        else if (ice_num == 3) {
            p[ice_num - 1]->icecream(left);
            p[ice_num - 1]->count(left);
            p[0]->show();
            p[1]->show();
            p[2]->show();
        }
        else
            cout << "잘못 입력하셨습니다.\n";

        cout << "계속 구매하시겠습니까(y/n)>>";
        cin >> choice;
        if (choice != "y") {
            cout << "\n";
            cout << "매출액 \n------------- \n";
            cout << "오늘의 아이스크림 총매출 : " << p[0]->all(left) + p[1]->all(left) + p[2]->all(left);
            break;
        }
        cout << endl;
    }
}

2 답변

  • virtual 키워드는 class 내의 멤버 함수 선언 부에서만 입력합니다. 멤버 함수의 정의에서 virtual을 입력하지 않습니다. 멤버 함수 정의는 다음과 같이 작성해야합니다.

    반환형 클래스 전체 이름::함수이름(파라미터 목록) { ... }

    따라서 ice1 :: virtual void show() { }void ice1 ::show() { }와 같이 작성해야 합니다.

    첨언으로 C++ 관련 질문은 질문 태그에 c++를 넣어 주세요.

  • C++ 에서 클래스, 함수 등을 사용할 때 선언(declaration)과 정의(definition) 을 구분 할 수 있어야 합니다.

    예를 들어 아래와 같이 main 함수에서 sum 함수를 호출하는 호출구문(function call statement)보다 함수 정의가 밑에 있는 경우 undefine 에러가 발생합니다.

    
    int sum(int, int); // <- 함수 원형 = function declaration
    
    int main(void)
    {
        int x = 100;
    
        int y = sum(x, 50);
        printf("sum: %d\n", y);
    
        return 0;
    }
    
    int sum(int a, int b) // <- 함수 정의 = function definition
    {
        return a+b;
    }
    

    컴파일러가 int y = sum(x, 50); 구문을 해석 할 때 이에 필요한 정보가 없기 때문인데요, 이를 방지하려면 main 함수 위에 int sum(int, int); 와 같이 함수 원형(function prototype)을 명시해주어야 합니다.

    이 때 함수 원형은 함수의 선언(declaration)에 해당합니다.

    이와 같은 원리로 header 파일 (.h or .hpp)과 source 파일 (.c or .cpp)을 구분 지을 때, declaration 부분은 헤더파일에 넣고, definition 부분은 소스 파일에 넣으시면 됩니다.

    virtual 구문은 declaration 문법에 속하니 definition 하는 부분에 들어가면 안됩니다.

    단 아래 소스에서

    Icecream(string in, int ice_c) { icename = in; ice_count = ice_c; }

    이렇게 declaration 과 동시에 definition 을 할 수도 있습니다.

    { } 로 감싸여진 부분이 들어가면 definition을 포함한 구문입니다. (보통 인라인 함수라고 부릅니다)

    
    #pragma once
    #ifndef ICECREAM_H
    #define ICECREAM_H
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    class Icecream {
    protected:
        string icename;
        int ice_count, sum = 0, sell = 0;
    public:
        Icecream(string in, int ice_c) { icename = in; ice_count = ice_c; }
        virtual void icecream(int left) { }
        virtual void show() { }
        virtual void count(int left) { }
        virtual int all(int left) { return sum; }
    };
    #endif
    
    

    그리고 이건 여담이지만

    아래에서 pragma once 와 ifndef ~ endif 구문은 같은 역할을 하기 때문에 둘 중에 한가지만 사용하셔도 됩니다.

    이 헤더 파일이 다른 곳에서 include 될 때 여러 번 include 되더라도 한번만 전처리 하겠다는 뜻입니다.

    (간단한건 pragma once 겠죠?)

    
    #pragma once
    #ifndef ICECREAM_H
    #define ICECREAM_H
    // ...
    // ...
    #endif
    
    
    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)