상속(inheritance)

Programming/C++ 2012. 6. 6. 20:19 |

상속은 적용이 중요한 문법이다. 적절할 때 선별적으로 적용할 수 있어야 한다.


#include <iostream>

#include <cstring>

using namespace std;


class PermenentWorker //데이터적 성격이 강한 클래스

{

    private:

        char name[100];

        int salary;


    public:

        PermenentWorker(char* name, int money)

            :salary(money)

        {

            strcpy(this->name, name);

        }

        int GetPay(void) const

        {

            return salary;

        }

        void ShowSalaryInfo(void) const

        {

            cout<<"name: "<<name<<endl;

            cout<<"salary: "<<GetPay()<<endl<<endl;

        }

};


class EmployeeHandler //기능적 성격이 강한 클래스(컨트롤 클래스)

{

    private:

        PermenentWorker* empList[50];

        int empNum;


    public:

        EmployeeHandler() :empNum(0)

{}

        void AddEmployee(PermenentWorker* emp) //새로운 직원정보 등록

        {

            empList[empNum++] = emp;

        }

        void ShowAllSalaryInfo(void) const         //모든 직원의 급여정보 출력

        {

            for(int i=0; i<empNum; i++)

                empList[i]->ShowSalaryInfo();

        }

        void ShowTotalSalary(void) const     //급여의 총액 출력

        {

            int sum=0;

            for(int i=0; i<empNum; i++)

                sum += empList[i]->GetPay();

            cout<<"salary sum: "<<sum<<endl;

        }

        ~EmployeeHandler()

        {

            for(int i=0; i<empNum; i++)

                delete empList[i];

        }

};


int main(void)

{

    EmployeeHandler handler;


    handler.AddEmployee(new PermenentWorker("asdf", 1000));

    handler.AddEmployee(new PermenentWorker("xcv", 2332));


    handler.ShowAllSalaryInfo();


    handler.ShowTotalSalary();

    return 0;

}



기능의 처리를 실제로 담당하는 클래스를 가리켜 '컨트롤(control) 클래스' 또는 '핸들러(handler) 클래스' 라 한다.


※ 컨트롤 클래스는 기능 제공의 핵심이 되기 때문에 모든 객체지향 프로그램에서 반드시 존재하는 클래스이다.




※ 멤버는 클래스가 정의될 때, 멤버의 초기화를 목적으로 정의된 생성자를 통해서 초기화하는 것이 가장 안정적이다. 그것이 비록 상속의 관계로 묶여있다 할지라도.


◆ 용어 정리 ◆


상위 클래스                                하위 클래스

기초(base) 클래스                      유도(derived) 클래스

슈퍼(super) 클래스                    서브(sub) 클래스

부모 클래스                               자식 클래스




#include <iostream>

using namespace std;


class Base

{

    private:

        int baseNum;

    public:

        Base(void) :baseNum(20)

        {

        cout<<"Base(void)"<<endl;

        }

        Base(int n) :baseNum(n)

        {

        cout<<"Base(int n)"<<endl;

        }

        void ShowBaseData()

        {

            cout<<baseNum<<endl;

        }

};


class Derived :public Base

{

    private:

        int derivedNum;

    public:

        Derived() :derivedNum(30)

        {

        cout<<"Derived()"<<endl;

        }

        Derived(int n) : derivedNum(n)

        {

        cout<<"Derived(int n)"<<endl;

        }

        Derived(int n1, int n2)

            : Base(n1), derivedNum(n2)

        {

            cout<<"Derived(int n1, int n2)"<<endl;

        }

        void ShowDerivedData()

        {

            ShowBaseData();

            cout<<derivedNum<<endl;

        }

};


int main(void)

{

    cout<<"case1......"<<endl;

    Derived dr1;

    dr1.ShowDerivedData();


    cout<<"case2........."<<endl;

    Derived dr2(12);

    dr2.ShowDerivedData();


    cout<<"case3..........."<<endl;

    Derived dr3(14, 15);

    dr3.ShowDerivedData();


    return 0;

}



위의 소스코드로 알 수 있는 점 두가지.

1. 유도 클래스의 객체 생성 과정에서 기초 클래스의 생성자는 100% 호출이 된다.

2. 유도 클래스의 생성자에서 기초 클래스의 생성자 호출을 명시하지 않으면, 기초 클래스의 void 생성자가 호출이 된다.


★ "클래스의 멤버는 해당 클래스의 생성자를 통해서 초기화해야 한다."




유도 클래스 객체의 소멸과정



위의 결과로 알 수 있는 사실.

1. 유도 클래스의 객체가 소멸될 때에는, 유도 클래스의 소멸자가 실행되고 난 다음에 기초 클래스의 소멸자가 실행된다.

2. 스택에 생성된 객체의 소멸순서는 생성순서와 반대이다.


※ 이러한 객체소멸의 특성 때문에 상속과 연관된 클래스의 소멸자는 "생성자에서 동적 할당한 메모리 공간은 소멸자에서 해제한다" 는 원칙을 지켜서 정의해야 한다.




#include <iostream>

#include <cstring>

using namespace std;


class Person

{

    private:

        char* name;

        

    public:

        Person(char* name)

        {

            this->name = new char[strlen(name)+1];

            strcpy(this->name, name);

        }

        ~Person()

        {

            delete []name;

        }

        void WhatYourName() const

        {

            cout<<"My name is "<<name<<endl;

        }

};


class UnivStudent : public Person

{

    private:

        char* major;


    public:

        UnivStudent(char* name, char* major)

            :Person(name)

        {

            this->major = new char[strlen(major)+1];

            strcpy(this->major, major);

        }

        ~UnivStudent()

        {

            delete []major;

        }

        void WhoAreYou() const

        {

            WhatYourName();

            cout<<"My major is "<<major<<endl<<endl;

        }

};


int main(void)

{

    UnivStudent st1("Jeon", "Houdini");

    st1.WhoAreYou();


    UnivStudent st2("Seo", "Maya");

    st2.WhoAreYou();


    return 0;

}



Posted by scii
: