본문 바로가기

C

c++ 상속 런타임에 결정되는 virtual, override, polymorphism, upcast

c++에서 클래스 상속 시

virtual 함수는 runtime 시간에 결정되게 만든다.

상속받는 함수를 override 할 때는 끝에 override를 붙인다.

 

그리고 destructor는 runtime에 소멸 되므로

virtual 로 만들어야 한다.

 

upcast는 상위클래스* polycat = new 하위클래스와 같은 형식인데.

(downcast)는 Cat* cat = (Cat*) polycat 과 같은 형식으로 한다

 

업캐스트를 하면 상위 클래스로 하위 클래스들을 한번에 다룰 수 있다.

다만 virtual로 함수를 만들어 주어야 조작이 된다.

 

코드 >>

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <iostream>
#include <array>
 
class Animal
{
public:
    Animal() {
        std::cout << "animal Constructor" << std::endl;
    }
    virtual ~Animal() = default// virtual -> runtime에 결정되게 한다.
                                 // virtual을 사용하지 않으면 상위 클래스가 소멸되어
                                 // 하위 클래스가 소멸되지 않는다.
    virtual void speak()
    {
        std::cout << "Animal" << std::endl;
    }
};
 
class Cat : public Animal
{
public:
    Cat()
    {
        std::cout << "cat Constructor" << std::endl;
    }
    ~Cat()
    {
        std::cout << "cat Destructor" << std::endl;
    }
    void speak() override // 상속을 받는다
    {
        std::cout << "meow~" << std::endl;
    }
};
 
class Dog : public Animal
{
public:
    Dog()
    {
        std::cout << "dog Constructor" << std::endl;
    }
    ~Dog()
    {
        std::cout << "dog Destructor" << std::endl;
    }
    void speak() override
    {
        std::cout << "bark~" << std::endl;
    }
};
 
int main()
{    /////////////////////////
    /// Stack 공간에 생성 ///
    /////////////////////////
    //Animal animal;
    // 상속 받은 것 실행
    // 먼저 Base class인 Animal Constructor가 실행된다
    // 이후 Derived Class인 Cat Constructor가 실행된다
    // 프로그램이 종료되면서 cat Destructor가 실행되고
    // 이후 Base Class인 Animal Class가 종료된다.
    //Cat cat;
 
    /////////////////////////
    //// Heap 공간에 생성 ///
    /////////////////////////
 
    //Animal* animalPtr = new Animal();
    //delete animalPtr;
 
    // 먼저 Base class인 Animal Constructor가 실행된다
    // 이후 Derived Class인 Cat Constructor가 실행된다
    // 프로그램이 종료되면서 cat Destructor가 실행되고
    // 이후 Base Class인 Animal Class가 종료된다.
    //Cat* catPtr = new Cat();
    //delete catPtr;
 
    /////////////////////////
    ////// Polymorphism /////
    /////////////////////////
 
    //Cat의 destructor가 안 생김
    //사실 base class의 destructor는 virtual이거나
    // protected로 선언이 되어야 한다
    Animal* polyCat = new Cat();// up casting
    // Cat* cat = (Cat*)polyCat // downcasting
    delete polyCat;
 
 
 
    //////////////////////////////////////////
    ////// Dynamic, Runtime Polymorphism /////
    //////////////////////////////////////////
    std::cout << "Animal vs Cat" << std::endl;
    int i = 0;
    std::cin >> i;
    Animal* polyAnimal;
    if (i == 1)
    {
        polyAnimal = new Cat();
    }
    else
    {
        polyAnimal = new Animal();
    }
    polyAnimal->speak();
    delete polyAnimal;
 
    // Dog Class
    // smart pointer를 사용해서 array를 만드는 것을 추천한다.
    // delete를 따로 부르지 않아도 되니까..
    std::cout << "5 animas array started..." << std::endl;
    std::array<Animal*5> animals;
    for (auto& animalPtr : animals)
    {
        int i = 0;
        std::cin >> i;
        if (i == 1)
        {
            animalPtr = new Cat();
        }
        else
        {
            animalPtr = new Dog();
        }
    }
 
    for (auto& animalPtr : animals)
    {
        animalPtr->speak();
        delete animalPtr;
    }
}