Hoon222y

[1220-5] 상속 / 오버라이딩 / 바인딩 / 업케스팅 본문

코딩/교육

[1220-5] 상속 / 오버라이딩 / 바인딩 / 업케스팅

hoon222y 2018. 12. 20. 21:21

상속 : 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것을 의미한다. 상속을 하는 주체를 부모 클래스하고 하고, 상속을 받는 주체를 자식클래스 라고 한다. 

 이때 상속되지 않는것은 : 생성자, 소멸자 , 대입연산자 , 정적멤버, friend 함수이다.  상속을 하려면 class 클래스명 : public 클래스명 으로 사용한다. 

그렇다면 상속에서 생성자와 소멸자는 어떻게 작동하는지 알아보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
 
//상속 관계에서 생성자와 소멸자의 호출 순서
//자식 생성자-> 부모 생성자 -> 자식 생성자 -> 자식 소멸자 -> 부모 소멸자
class Parent{
public:
    Parent(){ cout << "parent" << endl; }
    ~Parent(){ cout << "~parent" << endl; }
};
class Child : public Parent{
public:
    Child(){ cout << "child" << endl; }
    ~Child(){ cout << "~child" << endl; }
};
int main(){
    Child c;
}
cs


 해당 코드의 결과는 parent , child, ~child, ~parent로 동작한다. 또한 상속이 이루어질 경우 부모의 생성자를 임의적으로 선택할 수 있는데 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
class Parent{
    int age;
public:
    Parent(int a): age(a) { cout << "parent" << endl; }
    ~Parent(){ cout << "~parent" << endl; }
};
class Child : public Parent{
public:
    //멤버 이니셜라이저: 부모 생성자를 선택적으로 사용할 수 있음.
    //방법 : 자식 클래스() : 부모클래스 (...) {}
    Child(): Parent(0) { cout << "child" << endl; }
    ~Child(){ cout << "~child" << endl; }
};
int main(){
    Child c;
}
cs


해당처럼 자식클래스() : 부모클래스 () 로 사용한다. 이 때, parent 의 생성자 중 임의적으로 선택할 수 있는것이다. 이를 멤버 이니셜라이저라고 한다. 


상속이 이루어 질 경우 자식 클래스는 부모 클래스의 몇몇 변수들에 접근할 수 있는데 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
class Parent{
private:        int private_;
protected:      int protected_; //자식만 사용가능 하도록 할 때,  사용
public:         int public_;    //자식을 비롯한 나머지 객체들도 사용 가능
};
class Child : public Parent{
public:
    void foo(){
        //private_ = 0;         //에러, 물려받았으나 심볼이 보이지 앟아 접근 불가능
        protected_ = 0;         //가능    //둘다 가능한데 왜 protected?
        public_ = 0;            //가능
    }
};
int main(){
    Child c;
    //c.private_ = 0;           //에러 ,private 속성이므로
    //c.protected_ = 0;         //에러
    c.public_ = 0;
}
cs


 처럼 자식 클래스 내부에서는 부모의 protected 변수, public 변수를 사용할 수 있다. 하지만 외부에서는 public 변수만 사용할 수 있다(protected는 사용 불가)는 차이점이 있다. 



오버라이딩 : 자식 클래스가 부모 클래스인 함수를 재정의 하는것으로 부모함수의 시그니처(함수명, 리턴타입, 매개변수)와 완벽하게 동일해야 한다. 오버라이딩 된 함수 내에서 부모 함수를 호출하는 방법은 부모 클래스명::함수명(..)으로 호출한다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Rect{
public:
    void draw(){ cout << "draw rect" << endl; }
};
 
class RoundRect: public Rect{
public:
    //함수 오버라이딩 : 자식 클래스가 부모 클래스인 함수를 재정의 하는것
    // 정의 방법 : 부모 함수의 시그니처(함수명, 리턴타입, 매개변수)와 완벽하게 동일해야 한다.
    void draw(){
        //오버라이딩 된 함수안에서 부모 함수를 호출하는 방법
        //부모 클래스명::함수명(...);
        Rect::draw();
        cout << "draw Round rect" << endl;
    }
};
 
int main(){
    Rect r;
    r.draw();
    
    RoundRect rr;
    rr.draw();
}
cs


 

바인딩


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
 
class Rect{
public:
    void draw(){        //void draw(Rect* const this)
        cout << "draw rect" << endl;
    }
};
class RoundRect : public Rect{
public:
    void draw(){        //void draw(RoundRect* const this);
        cout << "draw Round rect" << endl;
    }
};
 
//바인딩 : 함수 호출과 실제 함수 기계어 코드를 연결하는 개념
// 정적 바인딩 : 컴파일 타임에 바인딩이 이루어짐
// 동적 바인딩 : 런타임(실행 중)에 바인딩이 이루어짐
int main(){
    Rect r;
    r.draw();       //draw(&r);
    
    RoundRect rr;
    rr.draw();      //draw(&rr);
}
cs


에서 하고싶은 말이 뭘까 ? 정의만 외울까 ... 


업케스팅 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
#include <iostream>
using namespace std;
 
//상속을 사용 하는 이유
//1. 문법적 : 코드의 재사용성
//2. 디자인 : 서로 다른 타입을 동종의 타입으로 처리하기 위함
class Human{};
class Marine : public Human{};
class Goast : public Human{};
 
class Hydra{};
 
int main(){
    
    //Human h;
    //Car* c = &h;          //에러
    
    Marine m;
    Goast g;
    //Human *human = &m;        //가능 , 업케스팅이라고 한다.
    
    Hydra h;
    //Human* grp[] = { &m, &g ,&h};     //에러
    void* grp2[] = { &m, &g, &h };
}
 
cs


Comments