은닉 효과
- #include <iostream>
- using namespace std;
- class AAA
- {
- public:
- void fct(){
- cout<<"AAA"<<endl;
- }
- };
- class BBB : public AAA
- {
- public:
- void fct(){ //AAA 클래스의 fct() 함수를 오버라이딩.
- cout<<"BBB"<<endl;
- }
- };
- int main(void)
- {
- BBB b;
- b.fct();
- return 0;
- }
소스코드와 같은 상황에서 "AAA 클래스의 fct 함수는 BBB 클래스에 의해서 오버라이딩 되었다" 라고 한다. B객체를 생성하면 그림과 같은 형태를 가지는데 오버라이딩 되면 A클래스의 fct 함수는 B 클래스의 fct 함수에 의해서 가려지게된다. (이것은 은닉됐다고 한다.)
23번째 줄의 b.fct();는 B클래스의 fct 함수를 호출하게 된다. 따라서, 오버라이딩이라는 특성이 은닉이라는 특성을 보여준다. 그럼 이 은닉된 A 클래스의 fct 함수는 사용할 수 없는 것인가? 그렇지 않다
바로 이 은닉된것을 보게 하는것이 바로 포인터이다. 포인터를 이용하면 아래 그림과 같이 B객체를 B클래스의 포인터로 가리키면은 B클래스로 바라고, B클래스의 fct 함수를 호출이 가능한것이고, A클래스의 포인터로 B클래스를 가르키면, 그것은 A클래스를 바라보는 것이 된다. 그렇기 때문에 클래스 포인터의 접근권한은 A클래스에 종속이 되는 것이다.
그러면 직접 그렇게 되는지 소스 코드를 이용해 알아 보자. 출력 결과를 보면 그렇게 된다는 것을 알 수 있을 것이다.
- #include <iostream>
- using namespace std;
- class AAA
- {
- public:
- void fct(){
- cout<<"AAA"<<endl;
- }
- };
- class BBB : public AAA
- {
- public:
- void fct(){
- cout<<"BBB"<<endl;
- }
- };
- int main(void)
- {
- BBB* b=new BBB;
- b->fct();
- AAA* a=b;
- a->fct();
- delete b;
- return 0;
- }
virtual : 그럼 멤버 함수를 가상으로 선언하면 어떻게 될까 가상이란 "실재 존재하지 않는것을 존재하는 것처럼 느끼게 하는것" 이다 fct 함수를 virtual로 선언하겠다. 이것은 원래는 이 함수는 없는 건데 내가 있는것 처럼 하겠다. 쉽게 말해 다시 말해 AAA 클래스 fct함수는 우리 눈에는 보이지만, 없는 것으로 해라는 말이다. 그럼 virtual 키워드를 쓰면 어떤 차이가 있는지 알아보자.
- #include <iostream>
- using namespace std;
- class AAA
- {
- public:
- virtual void fct(){
- cout<<"AAA"<<endl;
- }
- };
- class BBB : public AAA
- {
- public:
- void fct(){
- cout<<"BBB"<<endl;
- }
- };
- int main(void)
- {
- BBB* b=new BBB;
- b->fct();
- AAA* a=b;
- a->fct();
- delete b;
- return 0;
- }
메인에서 B클래스의 포인터로 A클래스의 포인터로 가르키고 있는데 a->fct(); 부분에서 A클래스의 포인터를 가르키면 A 클래스로 그 함수 부분을 호출 해야 할텐데 가리키는 곳을 가 봤더니 virtual 로 선언되어 있다. virtual은 없는것으로 치라는 것이다. 없으니까 어떤 것이라도출은 해야 하니 fct를 오버라이딩 하고 있는 BBB 클래스의 FCT 함수가 대신 호출이 일어 난다. 이런 특성이 바로 virtual을 이용한 재정의 이다. 그럼 우리는 다음과 같은 결론을 낼 수 있다.
오버라이딩은 virtual 키워드는 넣어 주지 않으면 은닉의 특성은 넣어 주면 재정의 특성을 가진다
댓글 없음:
댓글 쓰기