ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 명품 C++ Programming [8강] Open challenge - 상속 관계의 클래스 작성 (미완)
    컴퓨터공학 2019. 4. 8. 02:32

    Q. 다음과 같은 상속 관계를 가진 Product, Book, CompactDisk, ConverstationBook 클래스를 작성하고 아래 실행 화면과 같이 상품을 관리하는 프로그램을 작성하라. [난이도 7]

     

    Product 클래스는 상품의 식별자(id), 상품설명, 생산자, 가격을 나타내는 정보를 포함한다. Book 클래스는 ISBN 번호, 저자, 책 제목 정보를 포함한다. CompactDisc 클래스는 앨범 제목, 가수 이름 정보를 포함한다. ConverstaionBook은 회화 책에서 다루는 언어 명 정보를 포함한다. 객체 지향 개념에 부합하도록 적절한 접근 지정자, 멤버 변수 및 함수, 생성자 등을 작성하라. main()에서는 최대 100개의 상품을 관리하며, 모든 상품의 정보를 조회할 수 있다. 상품의 식별자는 상품을 등록할 때 자동으로 붙인다. 

    <이번 문제에 사용한 헤더와 소스>

    [주의를 기울인 점]

    1) C++의 특징에 최대한 준수하여 선언부와 구현부로 나눠서 작성하려 노력했다.
    2) 이번에 배운 상속과 접근 지정자 그리고 함수 오버라이딩을 적극 사용하려 노력했다.
    3) 변수와 함수의 이름을 잘 작성하여 최대한 코드 가독성을 높히려 노력했다.

     

    [만족스러운 점 및 잘한 점]

    1) 처음으로 진행한 C++ 프로젝트 실습인데 선언부와 구현부를 깔끔하게 구현하는데 성공했다.
    2) 상단에 신경썼던 점들을 모두 잘 구현하는데 성공했다.

    [아쉬운 점 및 부족했던 점]

    1) '<<' 연산자 오버로딩과 '상속 함수 오버라이딩'을 사용했지만 결국 최종 출력단계를 성공시키진 못했다.
    2) 포인터에 대한 개념 정립이 아직 많이 부족함을 느꼈다.
    3) 오류의 원인을 제대로 파악하는데 많은 시간이 걸렸다.
    4) const와 static등 지정어들의 의미를 명확히 알고 사용한다기 보다는 외워서 사용하는 느낌이 강했다.

    5) 동적할당 후 delete를 제대로 하지 못했다.

     

    [발생했던 오류 목록과 해결법]

    (1) C2360 Error, C2360 오류
    C2360: initialization of 'book' is skipped by 'case' label
    C2360: initialization of 'compactDisk' is skipped by 'case' label
    https://stackoverflow.com/questions/14669457/initialization-of-element-is-skipped-by-case-label 를 참고해서 해결할 수 있었다. 내 기억에는 C에서는 switch-case문에 괄호를 사용하지 않았던 기억이 있는데 C++에서는 각 Case마다 괄호를 넣어서 시작과 맺음을 깔끔하게 명시해줘야한다. 각 Case를 괄호로 묶어서 오류를 해결할 수 있었다.

     

    (2) identifier 'string' is undefined 오류, string 오류

    https://stackoverflow.com/questions/7146719/identifier-string-undefined

    https://stackoverflow.com/questions/28394815/c-visual-studio-class-error-identifier-string-is-undefined/28394856

    <string>헤더 파일을 추가해줘도 string은 표준 라이브러리에 있는 자료형이 아니고 std namespace에 있다보니 그냥 string이 아니라 std::string으로 범위 지정 연산자와 함께 써줘야한다. 소스에 있는 모든 string을 std::string으로 바꿔주니 오류가 해결됐다.


    (3) C2679 Error, C2679 오류

    C2679: no operator found which takes a right-hand operand of type

    https://stackoverflow.com/questions/22724064/error-c2679-binary-no-operator-found-which-takes-a-right-hand-operand-of

    처음에는 getWriter()같은 string 반환 멤버 함수를 void형으로 바꾼 뒤 cout으로 출력하는 형태의 함수를 만들었다. 따라서 cout << (void 형 함수) << endl 문장은 성립하지 않았고 위와같은 오류를 출력했다. 

     

     

    (4) LNK2019 Error, LNK2019 오류

    LNK2019: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits,class std::allocator > __thiscall Product::getDiscription(void)const " (?getDiscription@Product@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) referenced in function "class std::basic_ostream<char,struct std::char_traits > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits > &,class Product const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVProduct@@@Z) Project5 C:\Users\cydph\Documents\Visual Studio 2017\Projects\Project5\Project5\main.obj

     

     https://vaert.tistory.com/5를 참고해서 해결할 수 있었다.

    헤더파일에서 멤버 함수의 선언과 구현을 동시에 진행하고 visual studio의 리펙토링 기능을 사용했다. 헤더파일과 같은 이름을 가지는 cpp파일로 구현부가 자동으로 이동했고 굉장히 편리한 기능이라 생각한다. 그러나 cpp로 이동한 구현부는 inline함수로 선언이 됐고 헤더 파일에는 함수명 선언만 있으므로 이 inline 함수를 대입할 곳이 없기 때문에 링크 오류가 발생했다. 구현 부분에 inline을 제거해주니 오류가 해결됐다.

     

     

    [소스]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    //product.h
    #pragma once
    #include <iostream>
    #include <string>
     
    class Product
    {
    private:
        int m_id;
    protected:
        std::string m_discription;
        std::string m_productor;
        int m_price;
    public:
        Product(const int &id = 0const std::string &discription = "DEFAULT",
             const std::string &productor = "DEFAULT"const int &price = 0)
            : m_id(id), m_discription(discription), m_productor(productor), m_price(price)
        {}
        void setID(const int &id_in);
        void setDiscription(std::string &str_in);
        void setProductor(std::string &str_in);
        void setPrice(const int &price_in);
        
        int getID() const;
        std::string getDiscription() const;
        std::string getProductor() const;
        int getPrice() const;
     
        friend std::ostream & operator << (std::ostream &out, const Product &prod)
        {
            out << "--- 상품ID :" << prod.getID() << std::endl;
            out << "상품설명 : "<< prod.getDiscription()<< std::endl;
            out << "생산자 : "<< prod.getProductor()<< std::endl;
            out << "가격 : " << prod.getPrice() << std::endl;
            return out;
        }
    };
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include "product.h"
     
    void Product::setID(const int & id_in) { this->m_id = id_in; }
     
    void Product::setDiscription(std::string & str_in) { this->m_discription = str_in; }
     
    void Product::setProductor(std::string & str_in) { this->m_productor = str_in; }
     
    void Product::setPrice(const int & price_in) { this->m_price = price_in; }
     
    int Product::getID()  const { return m_id; }
     
    std::string Product::getDiscription()  const { return m_discription; }
     
    std::string Product::getProductor()  const { return m_productor; }
     
    int Product::getPrice()  const { return m_price; }
     
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    //book.h
    #pragma once
    #include "product.h"
     
    class Book : virtual public Product
    {
    private:
        int m_isbn;
    protected:
        std::string m_writer;
        std::string m_bookName;
    public:
        Book(const int &id = 0const std::string &discription = "DEFAULT",
            const std::string &productor = "DEFAULT"const int &price = 0,
            const std::string &bookName = "DEFAULT"const std::string &writer = "DEFAULT",
            const int &isbn = 0)
            : Product(id, discription, productor, price), m_bookName(bookName), m_writer(writer), m_isbn(isbn)
        {}
        void setISBN(const int & isbn_in);
        void setWriter(std::string &writer_in);
        void setBookName(std::string &bookName_in);
     
        int getISBN() const;
        std::string getWriter() const;
        std::string getBookName() const;
     
        friend std::ostream & operator << (std::ostream &out, const Book &book)
        {
            std::cout << static_cast<Product>(book);
            out << "ISBN : " << book.getISBN() << std::endl;
            out << "책제목 : "<< book.getBookName()<< std::endl;
            out << "저자 : "<< book.getWriter() << std::endl;
            return out;
        }
    };

    cs

     

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //book.cpp
    #include "book.h"
     
    void Book::setISBN(const int & isbn_in) { this->m_isbn = isbn_in; }
     
    void Book::setWriter(std::string & writer_in) { this->m_writer = writer_in; }
     
    void Book::setBookName(std::string & bookName_in) { this->m_bookName = bookName_in; }
     
    int Book::getISBN() const { return m_isbn; }
     
    std::string Book::getWriter() const { return m_writer; }
     
    std::string Book::getBookName() const { return m_bookName; }
     
    cs

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include "book.h"
     
    void Book::setISBN(const int & isbn_in) { this->m_isbn = isbn_in; }
     
    void Book::setWriter(std::string & writer_in) { this->m_writer = writer_in; }
     
    void Book::setBookName(std::string & bookName_in) { this->m_bookName = bookName_in; }
     
    int Book::getISBN() const { return m_isbn; }
     
    std::string Book::getWriter() const { return m_writer; }
     
    std::string Book::getBookName() const { return m_bookName; }
     
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    //compactDisk.h
    #pragma once
    #include "product.h"
     
    class CompactDisk : virtual public Product
    {
    protected:
        std::string m_singer;
        std::string m_albumName;
    public:
        CompactDisk(const int &id = 0const std::string &discription = "DEFAULT",
            const std::string &productor = "DEFAULT"const int &price = 0,
            const std::string albumName = "DEFAULT"const std::string & singer = "DEFAULT")
            :Product(id, discription, productor, price), m_albumName(albumName), m_singer(singer)
        {}
        void setSinger(std::string &singer_in);
        void setAlbumName(std::string &albumName_in);
     
        std::string getSinger() const;
        std::string getAlbumName() const;
        friend std::ostream & operator << (std::ostream &out, const CompactDisk &disk)
        {
            std::cout << static_cast<Product>(disk);
            out << "앨범제목 : "<< disk.getAlbumName()<< std::endl;
            out << "가수 : "<< disk.getSinger()<< std::endl;
            return out;
        }
    };
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include "compactDisk.h"
     
    void CompactDisk::setSinger(std::string & singer_in) { m_singer = singer_in; }
     
    void CompactDisk::setAlbumName(std::string & albumName_in) { m_albumName = albumName_in; }
     
    std::string CompactDisk::getSinger() const { return m_singer; }
     
    std::string CompactDisk::getAlbumName() const { return m_albumName; }
     
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    //conversationBook.h
    #pragma once
    #include "book.h"
     
    class ConversationBook : public Book
    {
    private:
        std::string m_lang;
     
    public:
        ConversationBook(const int &id = 0const std::string &discription = "DEFAULT",
            const std::string &productor = "DEFAULT"const int &price = 0,
            const std::string &bookName = "DEFAULT"const std::string &writer = "DEFAULT",
            const std::string &lang = "DEFAULT"const int &isbn = 0)
            :Book(id, discription, productor, price, bookName, writer, isbn), m_lang(lang)
        {}
     
        void setLang(const std::string &lang);
        std::string getLang() const;
        friend std::ostream & operator << (std::ostream &out, const ConversationBook &conv_book)
        {
            std::cout << static_cast<Book>(conv_book) << std::endl;
            out << "언어 : "<< conv_book.getLang()<< std::endl;
            return out;
        }
    };
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
    1
    2
    3
    4
    5
    6
    #include "conversationBook.h"
     
    void ConversationBook::setLang(const std::string & lang) { this->m_lang = lang; }
     
    std::string ConversationBook::getLang() const { return m_lang; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    #include "product.h"
    #include "book.h"
    #include "compactDisk.h"
    #include "conversationBook.h"
    using namespace std;
     
    int main()
    {
        int id = -1;
        bool flag = false;
        int price, isbn;
        string discription, productor, a_name, b_name, singer, writer, lang;
        Product* product[100];
     
        cout << "***** 상품 관리 프로그램을 작동합니다 *****" << endl;
        while (!flag)
        {
            cout << "상품 추가(1), 모든 상품 조회(2), 끝내기(3) ? ";
     
            int option;
            cin >> option;
            switch (option)
            {
            case 1:
            {
                cout << "상품 종류 - 책(1), 음악CD(2), 회화책(3) ? ";
                int specificOption;
                cin >> specificOption;
                cin.ignore(1);
                ++id;
                switch (specificOption)
                {
                case 1:
                {
                    cout << "상품설명 >> ";
                    getline(cin, discription);
                    cout << "생산자 >> ";
                    getline(cin, productor);
                    cout << "가격 >> ";
                    cin >> price; cin.ignore(1);
                    cout << "책제목 >> ";
                    getline(cin, b_name);
                    cout << "저자 >> ";
                    getline(cin, writer);
                    cout << "ISBN >> ";
                    cin >> isbn; cin.ignore(1);
                    Book *book = new Book(id, discription, productor, price,
                        b_name, writer, isbn);
                    product[id] = book;
                    break;
                }
                case 2:
                {
                    cout << "상품설명 >> ";
                    getline(cin, discription);
                    cout << "생산자 >> ";
                    getline(cin, productor);
                    cout << "가격 >> ";
                    cin >> price; cin.ignore(1);
                    cout << "엘범제목 >> ";
                    getline(cin, a_name);
                    cout << "가수 >> ";
                    getline(cin, singer);
                    CompactDisk *compactDisk = new CompactDisk(id, discription,
                        productor, price, a_name, singer);
                    product[id] = compactDisk;
                    break;
                }
                case 3:
                {
                    cout << "상품설명 >> ";
                    getline(cin, discription);
                    cout << "생산자 >> ";
                    getline(cin, productor);
                    cout << "가격 >> ";
                    cin >> price; cin.ignore(1);
                    cout << "책제목 >> ";
                    getline(cin, b_name);
                    cout << "저자 >> ";
                    getline(cin, writer);
                    cout << "언어 >> ";
                    getline(cin, lang);
                    cout << "ISBN >> ";
                    cin >> isbn; cin.ignore(1);
                    ConversationBook *conversationBook = new ConversationBook(id,
                        discription, productor, price, b_name, writer, lang, isbn);
                    product[id] = conversationBook;
                    break;
                }
                }
                cout << endl;
                break;
            }
            case 2:
            {
                for (int i = 0; i <= id; ++i)
                    cout << *(product[i]) << endl;
                break;
            }
            case 3:
            {
                flag = true;
                break;
            }
            }
        }
    }
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

     

     

     

    main()함수의 외부 Case 2번인 출력부분에서 *(product[i]) 부분이 가장 큰 문제점이다.
    원래 의도는 product[0]에는 compactDisk의 주소가, product[1]에는 book의 주소가 들어가서 << 연산자 오버로딩과 상속 함수 오버라이딩으로 product의 내용과 compactDisk 또는 book의 정보가 출력되는 것이다.
    그러나 *(product[i])에서 바로 product 클래스로 들어가버려 함수 오버라이딩이 일어나지 않고 상품설명, 생산자, 가격만 출력이 되고 return out; 되어버린다.
    또한 하단 부분에 디폴트 생성자를 볼 수 있다. 이는 product[1]에서 conversationBook 부분이 제대로 들어가지 않았다는 의미다. 이 부분에 대한 수정도 필요하다. 결국은 포인터에 대한 개념 부족이다.

     

    조언과 지적 그리고 도움은 언제든지 환영입니다! 감사합니다.

Designed by Tistory.