ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 상속
    플밍/C++ (overview) 2012. 1. 3. 23:03

    2006/08/05 17:24



    상속 등장 배경

     

    새로운 클래스가 추가되어도 프로그램의 다른 영역에는 전혀 변경이 가해지지 않았으면 좋겠다..

     

    예로, 자동차, 기차, 비행기..각각의 클래스를 만들면, 세가지는 모두 '탈것'이라는 공통점을

    가지고 있으므로, 분명히 공통적으로 포함되는 멤버를 가지게 될것이다.

    같은 문장을 세번이나 쓰는건 낭비다.

    그래서 그 공통점만 뽑아서 '탈것'이라는 클래스를 만들면 된다. 그다음, 각각의 교통수단에

    상속되어 사용되면 좋다.

     

    즉,

    상속을 당하는 base클래스는 좀더 추상적이고, 상속을 하는 derived클래스는 좀더 구체적이다.

     

    class AAA{

           int top;

    public:

           AAA();

           AAA(int i);

    };

     

    class BBB : public AAA{

    public:

           BBB();

           BBB(int j) : AAA(j);

    };

     

    int main(){

           BBB b1;

           BBB b2(10);

    }

     

    AAA를 base(혹은 super) class

    BBB를 derived(혹은 sub) class

     

    상속을 하는 객체의 생성 과정을 살펴보자.

     

    첫째. 메모리 공간 할당(상속되는 클래스도 감안해서 할당)

    둘째. base 클래스의 생성자 실행

    셋째. derived 클래스의 생성자 실행

     

    main에서 BBB형태의 b2을 생성했는데,

     

    우선 b2을 위한 메모리가 할당되고, (BBB가 AAA를 상속하고 있으므로, AAA의 공간도

    더해져져 할당된다.)

     

    생성자를 찾아 왔는데(생성자 호출은 했지만, 몸체는 아직 수행 전),

    BBB는 AAA를 상속하고 있는것이 아닌가?

     

    그래서 발길을 돌려 AAA로 가려고 하니, 멤버이니셜라이져가 AAA(j)형태의 생성자를 호출하라는

    메모가 남겨놨군. 

     

    그래서 AAA로 가서 AAA(j)형태의 생성자를 호출한 뒤, 다시 아까 가려다 만, BBB(int j)의

    몸체 부분으로 와서 나머지를 수행한다.

    (이니셜라이져가 없다면, 그냥 기본형인 BBB()을 호출한다.)

     

    (당연한 얘기겠지만, 상속관계라 하더라고 BBB에선 AAA에 있는 top을 조작할수 없다.

    왜? AAA에서 top은 private으로 선언되어 있으니까.. -_-)

     

    이번엔 객체의 소멸 과정을 살펴보자.

     

    base class : AAA

    sub class : BBB

    가 있을때, main에서 BBB를 생성해주면, 다음 순서대로 생성이 되고 소멸한다.

     

    base의 생성자 -> sub의 생성자 -> sub의 소멸자 -> base의 소멸자

     

    ===========================================================

     

    protected 키워드

     

    public 과 private은 명확히 알겠는데, protected는 무엇일까?

     

    상속관계에 있는 클래스 끼리는 공개하고, 여전히 그 밖에 외부에선 볼수 없게 하는 키워드이다.

     

    class AAA{                                            |     class AAA{                                  

    protected:                                            |     protected:                    

            int a;                                            |             int a;                     

    public:                                                  |      public:                      

            AAA(int _a){                                 |             AAA(){

                    a = _a                                  |                    ;  

            }                                                  |             }                

    };                                                         |      };              

                                                                |                      

    class BBB : public AAA{                        |      class BBB : public AAA{      

    public:                                                  |      public:                     

            BBB(int age) : AAA(age){         |              BBB(int age){                            

                    ;                                           |                      a = age;            

            }                                                  |               }                                                   

    };                                                         |     };                                                      

     

    두 코드를 비교해보자.

    AAA에서 a를 protected로 선언했기때문에, BBB에서도 a를 볼수 있다.

    BBB에선 age를 받아서 a에 저장을 하고 싶은데, 위의 코드에서처럼 두가지 방법이 있다.

     

    BBB에서 AAA의 생성자에 age를 넘겨서 AAA가 나머지 일을 하도록 하는 방법(왼쪽)

    BBB에서 a를 볼수 있으니 자신이 직접 a에 age를 저장하는 방법(오른쪽)

     

    결과적으로는 같은 일을 하고 있지만, 분명히 차이는 있다.

    결론부터 말하자면, 왼쪽 경우가 오른쪽 경우보다 결합도가 낮다. (low coupling)

     

    좋은 프로그래밍이란 low coupling, high cohesion이 잘 지켜진 프로그램을

    짜는 것이다.

     

    어떤 A, B클래스간의 결합도가 높다는 것은 A가 변경되면 B도 변경되어야할 위험이

    크단 뜻이다. 그런 귀찮은 일은 일으키고 싶지 않다.

     

    보통, derived클래스에서 base 클래스의 멤버 변수에 직접 접근하는 것은 일반적으로

    결합도를 높이는 결과를 가져온다.

     

    그러므로 public 멤버 함수를 통한 접근은 멤버 변수에 직접 접근하는 것에 비하면

    상대적으로 결합도를 덜 높인다고 말할수 있다.  

     

    ===========================================================

     

    세가지 형태의 상속

     

    가장 많이 쓰이는 형태가 public상속이고, 그 외에 protected, private 상속이 있다.

     

    base클래스에 private, public, protected 멤버가 각각 있다고 가정하고,

    base클래스를 세가지 형태로 상속을 시켜보자.

     

    derived클래스가 가지게 된 base클래스의 멤버들은 상속 성격에 따라 공개레벨에

    변동이 생긴다.

     

    예를 들어, base의 public멤버는 public상속에서는 그대로 public이고,

    protected상속에서는 protected로 변경된다.

     

                             |  public 상속   |   protected상속   |   private상속

    ---------------------------------------------------------------

    public 멤버       |     public         |      protected          |     private

    protected 멤버  |   protected      |      protected          |     private

    private 멤버      |   접근 불가     |      접근 불가         |    접근 불가

     

     

    그 공식은, X상속을 하면 X보다 공개범위가 넓은 멤버를 X로 맞춰준다.

    (나머지는 그대로. 그리고 잊지 말자. private은 상속을 하더라도 무조건 접근불가이다.)

     

Designed by Tistory.