C++/열혈 C++ 프로그래밍(윤성우 저)

열혈 C++ 프로그래밍 11-1 문제

꾸준함. 2017. 6. 12. 18:47

[1번 문제]

/*

Chapter 07에서는 예제 HASComposite.cpp를 통해서 다음의 두 클래스를 정의하였다(완전한 클래스의 정의는 예제 참고)

class Gun

{

        ....

}

 

class Police

{

private:

        int handcuffs; //소유한 수갑의 수

        Gun *pistol; //소유하고 있는 권총

public:

        ....

}

이에 Police 클래스를 대상으로 깊은 복사가 이뤄지도록 대입 연산자와 복사 생성자를 동시에 정의하고 이의 확인을 위해 main 함수도 적절히 정의해보자

*/

 

//HasComposite.cpp

/*

#include <iostream>

#include <cstring>

using namespace std;

 

class Gun

{

private:

        int bullet; //장전된 총알의 수

public:

        Gun(int bnum) :bullet(bnum)

        {

        }

        void Shot()

        {

               cout << "BBANG!" << endl;

               bullet--;

        }

};

 

class Police

{

private:

        int handcuffs; //소유한 수갑의 수

        Gun *pistol; //소유하고 있는 권총

public:

        Police(int bnum, int bcuff) :handcuffs(bcuff)

        {

               if (bnum > 0) //이전 예제와 달리 Gun 클래스를 상속하는 것이 아니라, 생성자에서 Gun 객체를 생성해서 이를 참조하고 있다

                       pistol = new Gun(bnum);

               else

                       pistol = NULL;

        }

        void PutHandCuff()

        {

               cout << "SNAP!" << endl;

               handcuffs--;

        }

        void Shot() //Gun 클래스를 상속한다면 별도의 Shot 함수를 정의할 필요가 없다. 그러나 Gun 객체를 멤버변수를 통해 참조하는 구조이기 때문에 이렇게 별도의 함수 정의

        {

               if (pistol == NULL)

                       cout << "Hut BBANG!" << endl;

               else

                       pistol->Shot();

        }

        ~Police()

        {

               if (pistol != NULL)

                       delete pistol;

        }

};

 

int main(void)

{

        Police pman1(5, 3);

        pman1.Shot();

        pman1.PutHandCuff();

 

        Police pman2(0, 3); //권총을 소유하지 않은 경찰

        pman2.Shot();

        pman2.PutHandCuff();

        return 0;

}

*/

 

#include <iostream>

#include <cstring>

using namespace std;

 

class Gun

{

private:

        int bullet; //장전된 총알의 수

public:

        Gun(int bnum) :bullet(bnum)

        {

        }

        void Shot()

        {

               cout << "BBANG!" << endl;

               bullet--;

        }

};

 

class Police

{

private:

        int handcuffs; //소유한 수갑의 수

        Gun *pistol; //소유하고 있는 권총

public:

        Police(int bnum, int bcuff) :handcuffs(bcuff)

        {

               if (bnum > 0) //이전 예제와 달리 Gun 클래스를 상속하는 것이 아니라, 생성자에서 Gun 객체를 생성해서 이를 참조하고 있다

                       pistol = new Gun(bnum);

               else

                       pistol = NULL;

        }

        Police(Police &ref) :handcuffs(ref.handcuffs) //복사 생성자

        {

               if (ref.pistol != NULL)

                       pistol = new Gun(*(ref.pistol));

               else

                       pistol = NULL;

        }

        Police &operator=(const Police &ref) //대입 연산자

        {

               cout << "Police& operator=()" << endl; //대입연산자 실행됬다고 출력

               handcuffs = ref.handcuffs;

               if (pistol != NULL)

                       delete pistol;

              

               if (ref.pistol != NULL)

                       pistol = new Gun(*(ref.pistol));

               else

                       pistol = NULL;

               return *this;

        }

        void PutHandCuff()

        {

               cout << "SNAP!" << endl;

                handcuffs--;

        }

        void Shot() //Gun 클래스를 상속한다면 별도의 Shot 함수를 정의할 필요가 없다. 그러나 Gun 객체를 멤버변수를 통해 참조하는 구조이기 때문에 이렇게 별도의 함수 정의

        {

               if (pistol == NULL)

                       cout << "Hut BBANG!" << endl;

               else

                       pistol->Shot();

        }

        ~Police()

        {

               if (pistol != NULL)

                       delete pistol;

        }

};

 

int main(void)

{

        Police pman1(5, 3);

        Police pman2 = pman1; //복사생성자의 호출

        pman2.PutHandCuff();

        pman2.Shot();

 

        Police pman3(2, 4);

        pman3 = pman1; //대입 연산자 호출

        pman3.PutHandCuff();

        pman3.Shot();

        return 0;

}

 


[2번 문제]

/*

Chapter 07의 문제 07-2의 두번 째 문제에서는 다음의 두 클래스 정의를 요구하였다.

class Book

{

private:

        char *title; //책의 제목

        char *isbn; //국제표준도서범ㄴ호

        int price; //책의 정가

        ....

};

 

class EBook :public Book

{

private:

        char *DRMKey; //보안관련 키

        ....

};

이 때 정의한 두 클래스를 대상으로 Book 클래스도, EBook 클래스도 깊은 복사가 진행이 되도록 복사생성자와 대입 연산자를 정의하고,

이의 확인을 위한 main 함수도 적절히 정의해보자.

참고로 이 문제의 해결을 위해서는 여러분이 생각해봐야 할 요소들이 몇 가지 존재한다.

특히 앞서 말한 다음 사실을 완전히 이해한 다음에 이 문제를 해결하기 바란다.

"C++에서, AAA형 참조자는 AAA 객체 또는 AAA를 직접 혹은 간접적으로 상속하는 모든 객체를 참조할 수 있다."

*/

#include <iostream>

#include <cstring>

using namespace std;

 

class Book

{

private:

        char *title; //책의 제목

        char *isbn; //국제표준도서번호

        int price; //책의 정가

public:

        Book(char *booktitle, char *bookisbn, int bookprice) :price(bookprice)

        {

               title = new char[strlen(booktitle) + 1];

               strcpy(title, booktitle);

               isbn = new char[strlen(bookisbn) + 1];

               strcpy(isbn, bookisbn);

        }

        Book(const Book &ref) :price(ref.price) //복사 생성자

        {

               title = new char[strlen(ref.title) + 1];

               strcpy(title, ref.title);

               isbn = new char[strlen(ref.isbn) + 1];

               strcpy(isbn, ref.isbn);

        }

        Book &operator=(const Book &ref) //대입 연산자

        {

               cout << "Book &operator=()" << endl; //대입연산자 호출을 출력

               delete[]title;

               delete[]isbn;

 

               title = new char[strlen(ref.title) + 1];

               strcpy(title, ref.title);

               isbn = new char[strlen(ref.isbn) + 1];

               strcpy(isbn, ref.isbn);

               price = ref.price;

               return *this;

        }

        void ShowBookInfo()

        {

               cout << "제목: " << title << endl;

               cout << "ISBN: " << isbn << endl;

               cout << "가격: " << price << endl;

        }

        ~Book()

        {

               delete[]title;

               delete[]isbn;

        }

};

 

class Ebook :public Book

{

private:

        char *DRMKey; //보안관련 키

public:

        Ebook(char *booktitle, char *bookisbn, int bookprice, char *key) :Book(booktitle, bookisbn, bookprice)

        {

               DRMKey = new char[strlen(key) + 1];

               strcpy(DRMKey, key);

        }

        Ebook(const Ebook &ref) :Book(ref) //복사생성자

        {

               DRMKey = new char[strlen(ref.DRMKey) + 1];

               strcpy(DRMKey, ref.DRMKey);

        }

        Ebook &operator=(const Ebook &ref) //대입연산자

        {

               cout << "Ebook &operator=()" << endl;

               Book::operator=(ref);

               delete[]DRMKey;

               DRMKey = new char[strlen(ref.DRMKey) + 1];

               strcpy(DRMKey, ref.DRMKey);

               return *this;

        }

        void ShowEBookInfo()

        {

               ShowBookInfo();

               cout << "인증키: " << DRMKey << endl;

        }

        ~Ebook()

        {

               delete[]DRMKey;

        }

};

 

int main(void)

{

        Ebook ebook1("좋은 C++ ebook", "555-12345-890-1", 10000, "fdx9w0i8kiw");

        Ebook ebook2 = ebook1; //복사 생성자의 호출

        ebook2.ShowEBookInfo();

        cout << endl;

        Ebook ebook3("gudetama", "gudetama", 0, "gudetama");

        ebook3 = ebook2; //대입 연산자의 호출

        ebook3.ShowEBookInfo();

        return 0;

}

개발 환경:Visual Studio 2017


지적, 조언, 질문 환영입니다! 댓글 남겨주세요~


[참고] 열혈 C++ 프로그래밍 윤성우 저

반응형