도순씨의 코딩일지

C++ :: 멤버함수와 가상함수의 동작원리 본문

𝐏𝐑𝐎𝐆𝐑𝐀𝐌𝐌𝐈𝐍𝐆/𝐂++

C++ :: 멤버함수와 가상함수의 동작원리

도순씨 2020. 8. 28. 00:00

먼저 단순한 코드를 하나 살펴보도록 하겠습니다.

 

🌼 멤버함수의 위치

⭐️RealObjUnder1.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
 
class Data{
private:
    int data;
public:
    Data(int num) : data(num) {}
    void ShowData() { cout << "Data: " << data << endl;}
    void Add(int num) {data += num;}
};
 
int main(void){
    Data obj(15);
    obj.Add(17);
    obj.ShowData();
    return 0;
}
cs

 

⭐️RealObjUnder1.cpp 실행결과

1
Data: 32
cs

 

위 예제를 C언어 스타일의 구조체와 전역함수를 이용해서 바꾸어보겠습니다.

 

⭐️ RealObjUnder2.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
 
// 클래스 Data를 흉내낸 영역
typedef struct Data{
    int data;
    void (*ShowData)(Data*);
    void (*Add)(Data*int);
}Data;
 
void ShowData(Data* THIS) { cout << "Data: " << THIS -> data << endl;}
void Add(Data* THIS, int num) {THIS -> data += num;}
 
// 적절히 변경된 main 함수
int main(void){
    Data obj1 = {15, ShowData, Add};
    Data obj2 = {7, ShowData, Add};
 
    obj1.Add(&obj1, 17);
    obj2.Add(&obj2, 9);
    obj1.ShowData(&obj1);
    obj2.ShowData(&obj2);
    return 0;
}
cs

 

⭐️ RealObjUnder2.cpp 실행 결과

1
2
Data: 32
Data: 16
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;
 
class AAA{
private:
    int num;
public:
    virtual void Func1() {cout << "Func1"<<endl;}
    virtual void Func2() {cout << "Func2" << endl;}
};
 
class BBB : public AAA{
private:
    int num2;
public:
    virtual void Func1() {cout << "BBB::Func1"<< endl;}
    void Func3() {cout << "Func3"<< endl;}
};
 
int main(void){
    AAA * aptr  = new AAA();
    aptr -> Func1();
 
    BBB * bptr = new BBB();
    bptr -> Func1();
    return 0;
}
cs

먼저 AAA 클래스를 살펴봅시다. virtual로 선언된 가상함수 두 개가 존재합니다. 이렇듯 한 개 이상의 가상함수를 포함하는 클래스에 대해서는 컴파일러가 '가상함수 테이블'이라는 것을 만듭니다. 가상함수 테이블은 실제 호출될 함수의 위치를 담고 있습니다.

 

key value
void AAA::Func1( ) 0x1024번지
void AAA::Func2( ) 0x2048번지

이러한 가상함수 테이블을 통해서 호출할 위치를 알 수 있습니다. 가상함수 테이블에는 오버라이딩 된 가상함수의 정보는 존재하지 않습니다.

 

 

Comments