본문 바로가기
강좌연구

[C++ 강좌연구] 정적 바인딩

by 두들낙서 2019. 2. 2.

저번 글에 올렸던 문제의 코드이다.


1
2
Derived d;
Base *= &d;
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
class Base {
public:
   void Print() {
      cout << "Base" << endl;
   }
};
 
class Derived : public Base {
public:
   void Print() {
      cout << "Derived" << endl;
   }
};
 
int main() {
   Base *= new Base();
   Derived *= new Derived();
 
   b->Print();
   d->Print();
   
   delete b;
   delete d;
}
cs


<출력 결과>

Base

Derived


포인터로 객체를 동적할당한 점 외에는 이전 예제와 차이가 없다.


문제는 이거다.


1
2
Base *b = new Derived();
b->Print();
cs


b는 Base 타입을 가리키는 포인터인데, 자식인 Derived 타입의 동적할당된 객체를 가리키고 있다.

즉 b 자체의 타입은 Base*인데, 가리키고 있는 대상의 타입은 Derived이다.


이런 경우에 b->Print()를 하게 되면 놀랍게도

Base

가 출력된다.


이유는 간단하다.

컴파일러가 b->Print() 를 만나는 순간, b의 타입을 확인한다. 

하지만 실제로 실행을 해보기 전까지는 b가 가리키고 있는 객체의 타입을 확정지을 수는 없다.

그래서 어쩔 수 없이 b가 가리키는 타입을 Base라고 결정지을 수밖에 없고, Base에서 정의된 멤버가 호출되는 것이다.

이렇게 실행 전에 객체의 타입을 결정짓는 것을 정적 바인딩이라고 한다.


정적 바인딩에서는 부모 클래스의 포인터를 통해서 자식 클래스의 고유 멤버를 사용할 수 없다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Base {
public:
   void Print() {
      cout << "Base" << endl;
   }
};
 
class Derived : public Base {
public:
   void PrintD() {
      cout << "Derived" << endl;
   }
};
 
int main() {
   Base *= new Derived();
 
   b->PrintD(); // 에러
 
   delete b;
}
cs


PrintD는 Base에는 없고 Derived에 정의된 함수이다.

이때 b->를 통해 PrintD를 사용하려 하면, 에러가 뜬다.

위의 케이스와 마찬가지로 b의 타입이 Base*로 인식되기 때문이다.


"어차피 자식의 멤버를 사용할 수 없다면, 굳이 부모 타입의 포인터를 써가면서 자식을 가리키는 이유는 뭔가요."


바로 동적 바인딩 때문이다.

동적 바인딩에 관해서는 다음 글에서 알아보자.

'강좌연구' 카테고리의 다른 글

[C++ 강좌연구] 동적 바인딩  (0) 2019.06.18
[C++ 강좌연구] 오버라이딩  (0) 2019.02.02

댓글