가상 함수
가상함수는 런타임 에 클래스의 다형성 을 구성하기 위해 사용한다. 자식 클래스에서 부모 클래스의 함수를 재정의하지 않을 시 부모 클래스의 함수를 호출한다. 상속관계에서 is-A 관계로 부모 클래스 자료형에 자식 클래스를 할당했을 때 자식 클래스에서 오버라이딩한 함수가 있다 해도 포인터는 자료형을 기준으로 판단 하기 때문에 부모 클래스의 함수를 호출한다. 이를 방지하기 위해 가상 함수를 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> using namespace std;class A {public : void pA () { cout<<"AA function" <<endl; } virtual void pB () { cout<<"AB function" <<endl; } }; class B : public A{public : void pA () { cout<<"BA function" <<endl; } void pB () override { cout<<"BB function" <<endl; } }; int main () { A *a = new B; a->pA (); a->pB (); B *b = new B; b->pA (); b->pB (); }
순수 가상 함수 자식 클래스에서 반드시 재정의 가 필요한 가상 함수이다. 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 #include <iostream> using namespace std;class A { public : virtual void virtual_function () { printf ("This is virtual function A\n" ); } void nomal_function () { printf ("This is normal function A\n" ); } A () { printf ("CREATE A\n" ); } virtual void pure_virtual () = 0 ; virtual ~A () { printf ("DESTROY A\n" ); } }; class B : public A{public : virtual void virtual_function () { printf ("This is virtual function B\n" ); } void normal_function () { printf ("This is normal function B\n" ); }; B () { printf ("CREATE B\n" ); } virtual void pure_virtual () { printf ("This is Pure virtual function()" ); } virtual ~B () { printf ("DESTROY B\n" ); } }; int main (int argc, char ** argv) { A *b = new B; b->nomal_function (); b->virtual_function (); b->pure_virtual (); delete b; }
가상 함수 테이블 클래스 내에 가상함수가 존재한다면 실제 객체가 가상함수를 실행할 때 어떤 주소의 함수를 실행 시킬지에 대한 정보를 담은 테이블이다. 가상 함수 테이블은 클래스별로 생성 된다.
가상 소멸자 자식 클래스를 소멸시킬 때 부모 클래스의 소멸자가 가상 소멸자가 아니라면 부모 클래스의 소멸자만 호출되고 memory leak 이 일어난다. 이를 방지하기 위해 부모 클래스의 소멸자를 가상 소멸자 로 지정하고 자식 클래스에서 소멸자를 선언해 자식 클래스도 소멸시켜야 한다.
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 #ifndef C__STUDY_VIRTUALCLASS_H #define C__STUDY_VIRTUALCLASS_H #endif #include <iostream> using namespace std;namespace VirtualClass { class A { public : A () { cout << "A 생성자" << endl; } ~A () { cout << "A 소멸자" << endl; } void f () { cout << "A function" << endl; } }; class B : public A { public : B () { cout << "B 생성자" << endl; } ~B () { cout << "B 소멸자" << endl; } void f () { cout << "B function" << endl; } }; class AA { public : AA () { cout << "AA 생성자" << endl; } virtual ~AA () { cout << "AA 소멸자" << endl; } virtual void f () { cout << "AA function" << endl; } }; class BB : public AA { public : BB () { cout << "BB 생성자" << endl; } ~BB () override { cout << "BB 소멸자" << endl; } void f () override { cout << "BB function" << endl; } }; void castingOperator () { B *b = new B (); A *a = dynamic_cast <A *>(b); a->f (); b->f (); A *prime_a = new B (); B *prime_b = static_cast <B *>(prime_a); prime_a->f (); prime_b->f (); AA *aa = new BB (); BB *bb = dynamic_cast <BB *>(aa); aa->f (); bb->f (); delete a; delete prime_a; delete aa; } void VirtualClassStudy () { A *b = new B (); b->f (); AA *bb = new BB (); bb->f (); delete b; delete bb; } }