C++/기초를 탄탄히 세워주는 C++ 프로그래밍 입문(황준하 저)

기초를 탄탄히 세워주는 C++ 프로그래밍 입문 8장 연습문제

꾸준함. 2017. 7. 4. 13:05

[8.1]

/*

다음 프로그램에서 잘못된 부분을 지적하고 수정해 본다.

현재 상속 액세스 지정자가 public으로 되어 있다.

엑세스 지정자가 protected private일 때는 어떻게 달라지는지 생각해 본다

*/

#include <iostream>

using namespace std;

 

class Base

{

//private:

public:

        int a;

//protected:

public:

        int b;

public:

        int c;

};

 

class Derived :public Base

{

private:

        //int d; //Derived 클래스 내에서는 접근 가능

        void func1()

        {

               a = 1; //public 상속을 하더라도 Base 클래스의 private 멤버 접근 불가

               b = 2;

               c = 3;

               d = 4;

               e = 5;

               f = 6;

        }

protected:

        //int e;//Derived 클래스 내에서는 접근 가능

        void func2()

        {

               a = 1; //public 상속을 하더라도 Base 클래스의 private 멤버 접근 불가

               b = 2;

               c = 3;

               d = 4;

               e = 5;

               f = 6;

        }

public:

        int d, e; //public 영역에 d, e를 선언해야 main에서도 접근 가능

        int f;//Derived 클래스 내에서는 접근 가능

        void func3()

        {

               a = 1; //public 상속을 하더라도 Base 클래스의 private 멤버 접근 불가

               b = 2;

               c = 3;

               d = 4;

               e = 5;

               f = 6;

        }

};

 

int main(void)

{

        Derived dObj;

        dObj.a = 1; //public 영역에 선언된 c f만 접근 가능

        dObj.b = 2;

        dObj.c = 3;

        dObj.d = 4;

        dObj.e = 5;

        dObj.f = 6;

 

        return 0;

}


[8.2]

/*

다음 프로그램의 출력 결과가 무엇인지 설명해 본다

*/

#include <iostream>

using namespace std;

 

class Base

{

protected:

        int num;

public:

        Base() :num(0)

        {

               cout << "생성자 Base(" << num << ")" << endl;

        }

        Base(int n) :num(n)

        {

               cout << "생성자 Base(" << num << ")" << endl;

        }

        ~Base()

        {

               cout << "소멸자 Base(" << num << ")" << endl;

        }

};

 

class Derived :public Base

{

public:

        Derived()

        {

               cout << "생성자 Derived(" << num << ")" << endl;

        }

        Derived(int n) :Base(n)

        {

               cout << "생성자 Derived(" << num << ")" << endl;

        }

        ~Derived()

        {

               cout << "소멸자 Derived(" << num << ")" << endl;

        }

};

 

Derived d1; //Base() 생성자 호출 후 Derived() 생성자 호출

 

void main(void)

{

        Derived *d2 = new Derived(1);//Base(1) 생성자 호출 후 Derived(1) 생성자 호출

        Derived d3(2); //Base(2) 생성자 호출 후 Derived(2) 생성자 호출

 

        delete d2; //원래는 호출된 순서의 역순으로 소멸해야 하나 delete문이 나왔으므로 Derived(1) 소멸 후 Base(1) 소멸 그리고 나머지 소멸

}

 

[8.3]

/*

다음과 같은 CPoint 클래스와 CCircle 클래스를 작성하되 CCircle 클래스는 CPoint 클래스로

부터 상속받아 구현하고, 이를 테스트하기 위한 main 함수도 구현해 본다.

CPoint 클래스의 멤버 변수로는 좌표(int x, y)를 포함하고 Move, Draw 멤버 함수를 포함한다.

CCircle 클래스는 멤버 변수로 중심 좌표(int x, y)와 반지름(double Radius)을 포함하고,

멤버함수로는 Move, Draw, GetArea를 포함한다.

이 때 Move는 두 클래스 모두 동일한 역할을 하며 Draw는 두 클래스가 서로 다른 내용으로 구현되어야 한다.

*/

#include <iostream>

using namespace std;

 

#define PI 3.14

 

class Point

{

private:

        int x, y;

public:

        Point(int a = 0, int b = 0) :x(a), y(b)

        {

        }

        void Move(int c, int d)

        {

               x += c;

               y += d;

        }

        void Draw()

        {

               cout << "중심: ";

               cout << "(" << x << ", " << y << ")" << endl;

        }

};

 

class CCircle :public Point

{

private:

        double Radius;

public:

        CCircle(int a = 0, int b = 0, double r = 1) :Point(a, b), Radius(r)

        {

        }

        void Draw()

        {

               Point::Draw();

               cout << "반지름: ";

               cout << Radius << endl;

        }

        double GetArea()

        {

               return (PI*Radius*Radius);

        }

};

 

int main(void)

{

        Point p(1, 1);

        p.Draw();

        p.Move(2, 2);

        p.Draw();

 

        CCircle c(1, 1, 3);

        c.Draw();

        c.Move(3, 3);

        c.Draw();

        cout << "원의 넓이는: " << c.GetArea() << endl;

        return 0;

}

[8.4]

/*

그림 8.7과 같은 클래스들이 존재한다.

CDate는 날짜를 저장하기 위한 클래스이고,

CTime은 시간을 저장하기 위한 클래스이며,

CDateTime은 날짜와 시간을 동시에 저장할 수 있다.

ToDo 변수는 해당 시간에 해야 할일을 의미하는 문자열이다.

이 클래스들의 상속 관계를 따져 보고 그에 따라 프로그램을 작성해 본다

*/

#include <iostream>

#include <cstring>

using namespace std;

 

class CDate

{

private:

        int Year;

        int Month;

        int Day;

public:

        CDate(int a = 2017, int b = 7, int c = 4) :Year(a), Month(b), Day(c)

        {

        }

        void Print()

        {

               cout << Year << " " << Month << " " << Day << "" << endl;

        }

};

 

class CTime

{

private:

        int Hour;

        int Minute;

        int Second;

public:

        CTime(int a = 12, int b = 24, int c = 30) :Hour(a), Minute(b), Second(c)

        {

        }

        void Print()

        {

               cout << Hour << " " << Minute << " " << Second << "" << endl;

        }

};

 

class CDateTime :public CDate, public CTime

{

private:

        char ToDo[50];

public:

        CDateTime(int a, int b, int c, int d, int e, int f, char *string) :CDate(a, b, c), CTime(d, e, f)

        {

                strcpy(ToDo, string);

        }

        void Print()

        {

               CDate::Print();

               CTime::Print();

               cout << "현재 시각에 할 일: " << ToDo << endl;

        }

};

 

int main(void)

{

        CDateTime CDT(2017, 7, 4, 12, 26, 30, "빈둥빈둥");

        CDT.Print();

        return 0;

}

 

[8.5]

/*

예제 8.11의 프로글매에서 CPointXY CPointXZ 클래스 작성 시 CPointX 클래스를 virtual base 클래스로 상속받고,

이에 따라 프로그램이 동작할 수 있도록 수정한다.

그리고 출력결과를 분석해 보고 어떻게 달라졌는지 설명해본다

*/

#include <iostream>

using namespace std;

 

class CPointX

{

protected:

        int x;

public:

        CPointX() //virtual 선언시 필요한 생성자

        {

               cout << "CPointX 디폴트 생성자" << endl;

        }

        CPointX(int a) :x(a)

        {

               cout << "CPointX 생성자" << endl;

        }

        ~CPointX()

        {

               cout << "CPointX 소멸자" << endl;

        }

        void Print()

        {

               cout << "CPointX" << endl;

        }

};

 

class CPointXY :virtual public CPointX //virtual 추가

{

protected:

        int y;

public:

        CPointXY(int a, int b) :CPointX(a), y(b)

        {

               cout << "CPointXY 생성자" << endl;

        }

        ~CPointXY()

        {

               cout << "CPointXY 소멸자" << endl;

        }

        void Print()

        {

               cout << "CPointXY" << endl;

        }

};

 

class CPointXZ :virtual public CPointX //virtual 추가

{

protected:

        int z;

public:

        CPointXZ(int a, int c) :CPointX(a), z(c)

        {

               cout << "CPointXZ 생성자" << endl;

        }

        ~CPointXZ()

        {

               cout << "CPointXZ 소멸자" << endl;

        }

        void Print()

        {

               cout << "CPointXZ" << endl;

        }

};

 

class CPointXYZ :public CPointXY, public CPointXZ

{

private:

        int xyz;

public:

        CPointXYZ(int a, int b, int c) :CPointXY(a, b), CPointXZ(a, c), xyz(0)

        {

               cout << "CPointXYZ 생성자" << endl;

        }

        ~CPointXYZ()

        {

               cout << "CPointXYZ 소멸자" << endl;

        }

        void Print()

        {

               CPointX::Print(); //CPointX 생성자가 한번만 호출된다

               CPointXY::Print();

               CPointXZ::Print();

               cout << "CPointXYZ" << endl;

        }

};

 

int main(void)

{

        CPointXYZ Pxyz(1, 2, 3);

        Pxyz.Print();

        return 0;

}

 

[8.6]

/*

그림 8.9와 같은 상속 관계에 대해 생각해 본다.

최종적으로 클래스 B에는 클래스 A 객체가 2개 존재해야 한다.

클래스 X, Y, Z, B를 어떻게 구현해야 할까?

상속관계(virtual base 클래스 여부)만 답해 보도록 한다

*/

#include <iostream>

using namespace std;

 

class A

{

public:

        A()

        {

               cout << "A 생성자" << endl;

        }

        ~A()

        {

               cout << "A 소멸자" << endl;

        }

};

 

class X :public virtual A

{

public:

        X()

        {

               cout << "X 생성자" << endl;

        }

        ~X()

        {

               cout << "X 소멸자" << endl;

        }

};

 

class Y :public virtual A

{

public:

        Y()

        {

               cout << "Y 생성자" << endl;

        }

        ~Y()

        {

               cout << "Y 소멸자" << endl;

        }

};

 

class Z :public virtual A

{

public:

        Z()

        {

               cout << "Z 생성자" << endl;

        }

        ~Z()

        {

               cout << "Z 소멸자" << endl;

        }

};

 

class B :public virtual X, public virtual Y, public virtual Z

{

public:

        B()

        {

               cout << "B 생성자" << endl;

        }

        ~B()

        {

               cout << "B 소멸자" << endl;

        }

};

 

int main(void)

{

        B(); //virtual을 적절히 사용하면 A 생성자가 한번만 호출된다

        return 0;

}

[8.7]

/*

다음 프로그램이 동작할 수 있도록 CPoint 클래스에 필요한 멤버 함수를 작성해 본다.

CPoint 클래스의 생성자가 private에 있는 상태로 구현해야만 한다

*/

#include <iostream>

using namespace std;

 

class CPoint

{

private:

        int x, y;

        CPoint(int a, int b) :x(a), y(b)

        {

        }

        static CPoint *OnlyPoint; //유일한 CPoint 객체를 가리킬 포인터

public:

        //여기서부터 추가

        static CPoint GetPoint(int a, int b)

        {

               if (OnlyPoint != NULL)

               {

                       delete OnlyPoint; //존재할경우 delete를 해야한다

                       OnlyPoint = new CPoint(a, b);

               }

               else

                       OnlyPoint = new CPoint(a, b);

               return *OnlyPoint;

        }

        void Print()

        {

               cout << "(" << x << ", " << y << ")" << endl;

        }

};

 

CPoint *CPoint::OnlyPoint = NULL;

 

int main(void)

{

        CPoint P1 = CPoint::GetPoint(1, 2);

        CPoint P2 = CPoint::GetPoint(3, 4);

 

        P1.Print();

        P2.Print();

        return 0;

}


개발 환경:Visual Studio 2017


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


[참고] 기초를 탄탄히 세워주는 C++ 프로그래밍 입문 황준하 저


반응형