열혈 강의 9장


함수 포인터 공부하자.


oop 프로젝트 6단계

--> AAA 클래스 내의 함수 virtual void show() { ... }

BBB 클래스 내의 함수 virtual void show() { 


AAA::show();

....

....


}


---> 유용하게 쓸 일이 많으니 꼭 기억할 것!!



1. virtual 소멸자의 필요성


/////////////////////////////////////////// Base 클래스 AAA 선언


class AAA{


private:

char* name1;


public:

AAA(char* _name1) {


name = new char[strlen(_name1)+1];

strcpy(name, _name);

}

~AAA(){

delete []name1;

}

}


////////////////////////////////////////// AAA를 상속하는 Derived 클래스 BBB


class BBB : public AAA{


private:

char* name2;


public:

BBB(char* _name1, char* _name2) : AAA(_name){


name2 = new char(strlen(_name2)+1];

strcpy(name2, _name2);


}

~BBB(){

delete []name1;

}

}


////////////////////////////////////////////// 메인 함수


int main(){


AAA* a = new BBB("aaa", "bbb");  ///// 1번

BBB* b = new BBB("aaa","bbb");  ///// 2번


}



2번의 경우 :


소멸의 주체가 되는 포인터가 BBB 객체 포인터이다.

BBB의 소멸자 호출 후 AAA의 소멸자도 호출

--> 메모리 반환이 정상적으로 일어난다.


1번의 경우 :


소멸의 주체가 되는 포인터가 AAA 객체 포인터이다.

AAA의 소멸자만 호출하고 BBB의 소멸자는 호출하지 않는다.

--> 메모리 유출이 일어난다.


--> 가리키는 객체가 무엇이든 AAA의 포인터이기 때문에 AAA의 객체로 바라본다.



////////////////////////////////////////////////////////////// 해결책


---> 해결책 : virtual 소멸자를 이용한다!!


virtual ~AAA(){

delete[] name1;

}


소멸자를 호출하려 들어갔는데, 가상함수로 선언 되어있다,

때문에 AAA를 상속하는 BBB의 소멸자를 호출한다.

그리고 또 다시 AAA의 소멸자를 호출하게 된다.

--> 특성 그 자체로 이해하기!!



2. virtual table


멤버함수는 객체 내에 존재하지 않는다.

코드영역이란?


객체를 여러개 만들 경우 여러개의 멤버함수 또한 만들어지게 된다. --> 비효율적이다.


때문에 코드영역에 멤버함수를 단 하나만 만들어 놓고

객체들이 공유하며 사용한다


////////////////////////////////////////////////// ex


class AAA{


int n;


public:

void Add(){

n++;


}

}


Add() 함수가 코드 영역에 들어가게 된다.


단,

--> Add(A* a){

(a->n)++;

}


이러한 형태로 변형되어 저장되며, 호출할 경우 Add의 인자로 객체의 포인터가 전달되어진다.


////////////////////////////////////////////////virtual table


virtual table은 key 값과 value 값이 있다.

key값은 어떠한 함수인지 구분해주는 역할을 하고, value값은 그 함수의 주소값을 지닌다.



객체 내에서 함수가 단 하나라도 virtual로 선언될 경우 (1개 이상)

그 클래스 내의 모든 함수(virtual이 아니라도)의 정보를 가지는 virtual table이 만들어진다.


때문에 함수가 호출 될 때에는 virtual table을 거쳐서 코드영역에 있는 함수를 찾게 된다.


virtual을 선언하지 않을 경우 바로 코드영역의 함수를 찾았지만 virtual table을 거쳐서 함수호출을 하게 된다.(virtual이든 아니든) ---> 단점.

따라서 메모리 또한 추가된다. (4byte)


AAA클래스의 멤버함수 virtual void fct()

virtual void show();


AAA를 상속하는 BBB클래스의 멤버함수 virtual void fct()

void fct2();


BBB클래스에서 virtual이 선언 되었기 때문에 virtual  table이 만들어지게 된다.

그 테이블에는 fct(), fct2() 그리고 AAA를 상속했기 때문에 show()의 정보 또한 저장된다.


AAA클래스의 virtual table에는 fct()와 show()의 정보


AAA의 fct() BBB의 fct()는 virtual table에 저장된 주소값이 다르다 --> 오버라이딩 되었지만 다른 함수이기 때문


--> 때문에 fct()는 AAA의 virtual table에도 BBB의 virtual table에도 저장되게 된다.


다만 BBB의 virtual table에는 재정의 되기전의 fct()의 정보가 전혀 없다. --> 가상함수의 원리


AAA* a = new BBB(); 의 가상함수 원리

'C++' 카테고리의 다른 글

[C++] 레퍼런스 정리  (0) 2016.12.07
[C++] 연산자 오버로딩 // 열혈강의  (0) 2016.12.07
[C++] 상속에 대하여 // 열혈강의  (0) 2016.12.01
[C++] 기초4 // 열혈강의  (0) 2016.12.01
[C++] 기초3 // 열혈강의  (0) 2016.11.30

+ Recent posts