열혈 강의 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 |