[C++] 6. 상속

2011. 5. 24. 22:50C++


[C++] 상속

1. 상속의 기본
 상속을 하게 되면 아래와같이 수행된다.
 - 메모리 공간 할당( Base 클래스와 Derived 클래스에 대한것 모두)
 - Base 클래스의 생성자 실행
 - Derived 클래스의 생성자 실행

 ex> class Student : public Person

 - 생성자 호출 순서
   Base > Derived

   * 하위 생성자안에 상위 생성자가 명시되어 있지 않으면 디폴트 생성자(Void)가 호출됩니다.

 - 상위의 생성자를 지정하는 방법

   class Person {
       Person(int value){}
   }

   class Student: public Person{
       Student(char*name, int value): Person(value) // 이와같이 부모클래스의 생성자를 지정 가능
       {
       }
   }

 - 소멸자의 호출 순서
   * 자식 클래스의 소멸자부터 호출됩니다.

   자식 클래스의 소멸자 > 부모 클래스의 소멸자 > 메모리 반환

 - 상속에 관련된 접근 제한
   protected 로 선언된 변수 및 함수는 상속관계에 있는 클래스에서 접근이 가능합니다.
   (단, 외부에서는 접근이 불가합니다.)

2. 세가지 형태의 상속
 - Base 클래스의 멤버는 상속되는 과정에서 접근 권한이 변경 됩니다.


   class Student: public Person // 대부분의 상속, 부모클래스의 protected와 public만 접근 가능
   class Student: protected Person // 부모클래스의 public 변수/함수들이 모두 protected로 변환
   class Student: private Person // 부모클래스의 public 변수/함수들이 모두 private 로 변환

   단) 부모클래스의 private 변수 자식 클래스에는 어떤 경우라도 접근 불가하다.


3. 객체 포인터
 - 객체의 주소값을 저장할 수 있는 포인터

 - Base 클래스의 포인터는 Base 객체 뿐만 아니라 Derived 클래스 객체의 주소값도 저장 가능하다.

 - Base 클래스의 포인터의 접근은 Base 클래스의 멤버를 먼저 가리킨다.
   즉 Base* b = new Derived 라 했을때, Derived에 log() 함수가 있을지라도 b.log() 했을때
   Base의 log() 함수가 실행된다.

   Person => Student => FirstGradeStudent 의 상속관계 일때
   class Student : public Person
   class FirstGradeStudent : public Student

   Person* p = new Student; //가능
   Person* p = new FirstGradeStudent; // 가능
   Student* s = new FirstGradeStudent; // 가능



4. 객체 레퍼런스
 - 객체를 참조할 수 있는 레퍼런스
 - 클래스 포인터의 특성과 일
 - 객체를 참조하는 레퍼런스의 권한은 클래스 포인터의 권한과 일치 합니다.

   FirstGradeStudent& fgs;
   Person& p =  fgs;
   Student& s = fgs;

5. 오버라이딩
 - Base 클래스에 선언된 멤버와 같은 형태의 멤버를 Derived 클래스에서 선언
   class Person {
       virtual log(char* msg){}
   }

   class Student: public Person{
       log(char* msg){}
   }

   Person* p = new Student;
   p->log(); // Student의 log 함수가 호출된다. (virtual 가상함수로 선언되었기 때문에)

   * 하위 클래스의 가상함수내에서 상위의 가상함수 호출 방법
     Person::log();

 - 멤버 함수를 가상(virtual)으로 선언하기
   * virtual 특성도 상속된다. (자식클래스에 해당 함수도 자동으로 virtual이 된다.)


6. 순수 가상함수와 추상 클래스
 - 추상 클래스: 순수 가상함수를 1개 이상 가지고 있는 클래스를 말한다.
                # 객체화 불가함.

 - 순수 가상함수: 선언만 하고 정의 안하는 방법
   virtual int log()=0; // 이와 같이 하면 선언만 하게 된다.

7. 상속관계에서의 소멸자 문제점과 해결

   * delete 할때의 문제점  
   class Person {
       virtual log(char* msg){}
   }

   class Student: public Person{
       log(char* msg){}
   }

   int main() {
       Person* p = new Student;
       delete p; // Person 클래스내의 소멸자만 호출되어 메모리 릭이 발생한다.
   }

   => 이문제를 해결하기 위해서는 Base 클래스의 소멸자에 virtual를 선언하면 된다.
      그러면 해당 소멸자는 자동으로 하위/상위 클래스를 해제하게 된다.

      virtual ~Person(){}