'virtual상속'에 해당되는 글 1건

9장정리

C++프로그래밍/C++ 2007. 7. 22. 19:48

1. 클래스 멤버함수는 사실 어디에?

#include <iostream>

using std::cout;
using std::endl;

class Data{
 int data;
public:
 Data(int num){
  data=num;
 }
 void ShowData(){
  cout<<"Data : "<<data<<endl;
 }
 void add(int num){
  data+=num;
 }
};

int main()
{
 Data ddd(10);
 ddd.add(10);
 ddd.ShowData();

 Data eee(20);
 eee.add(20);
 eee.ShowData();

 return 0;
}

2개의 객체를 생성할 경우 멤버함수도 2번 호출하는데 이는 생성되는 객체마다 멤버함수가
존재하는 것이 아니다. 함수이름은 메모리 상에 존재하는 함수를 가리키는 포인터와 같다.
(상수포인터). 컴파일을 할때 이미 메모리 상에 올라간후 런타임에 함수포인터를 이용하여
불러온다고 해야하나..맞나..아무튼 객체를 100개 생성하더라도 메모리에 올라가는 함수는
하나이고 그 100개의 객체는 함수포인터로 메모리에 올라가있는 함수를 호출하여 사용한다.
즉 모든 객체가 함수 하나를 공유하는 형태를 취한다.

2. 가상함수가 동작하는 원리

 #include <iostream>

using std::cout;
using std::endl;

class A{
 int a;
 int b;
public:
 virtual void fct1(){cout<<"fct1()"<<endl;}
 virtual void fct2(){cout<<"fct2()"<<endl;}
};
class B : public A{
 int c;
 int d;
public:
 virtual void fct1(){cout<<"Overriding fct1()"<<endl;}
 void fct3(){cout<<"fct3()"<<endl;}
};

int main()
{
 A* aaa= new A();
 aaa->fct1();

 B* bbb=new B();
 bbb->fct1();
 return 0;
}

A클래스에 가상함수가 2개가 존재한다. 저렇게 1개 이상의 클래스를 포함하는 클래스에 대해서 컴파일러는 가상함수 테이블이라는 것을 만들어준다. 이 테이블은 실제 호출되어야할 함수의 위치정보를 가지고 있는 테이블이다.

사용자 삽입 이미지

<가상함수테이블>
<내가 돈주고 산 열혈강의 C++ ppt자료에서 캡춰>


가상함수 테이블은 key와value가 있는데 key값은 호출하고자 하는 함수를 구분지어주는것이고 value는 해당 함수의 위치를 가르쳐 주는 역할을 한다.

위의 예제에서 객체를 생성하면 다음과 같은 현상이 벌어지게 된다.

사용자 삽입 이미지

<가상함수 테이블과 가상함수와의 관계>
<내가 돈주고 산 열혈강의 C++ ppt자료에서 캡춰>



하나이상의 가상함수를 멤버로 지니는 클래스 객체는 가상함수 테이블을 가리킬수 있는 포인터가 추가된다.
가상함수를 포함하지 않은 클래스는 가상함수 테이블을 생성하지 않는다.

3. 다중상속에 대한이해
다중 상속이란 하나의 Derived 클래스가 둘이상의 Base를 상속하는것을 말한다.

#include <iostream>

using std::cout;
using std::endl;

class AAA{
public:
 void String1(){
  cout<<"AAA::String1()"<<endl;
 }
};

class BBB{
public:
 void String2(){
  cout<<"BBB::String2()"<<endl;
 }
};

class CCC : public AAA,public BBB{
public:
 void ShowString(){
  String1();
  String2();
 }
};

int main(){
 CCC ccc;
 ccc.ShowString();
 return 0;
}


클래스 CCC는 클래스 AAA와BBB를 동시에 상속하고 있다.
별 문제 없는 코드이다..실행결과도 아주 만족하게 나오고... 그! 러! 나!

#include <iostream>

using std::cout;
using std::endl;

class AAA{
public:
 void String1(){
  cout<<"AAA::String1()"<<endl;
 }
};

class BBB :  public AAA{
public:
 void String2(){
  cout<<"BBB::String2()"<<endl;
 }
};

class CCC :  public AAA{
public:
 void String3(){
  cout<<"CCC::String3()"<<endl;
 }
};

class DDD : public BBB, public CCC{
public:
 void ShowString(){
  String1();
  String2();
  String3();
 }
};
int main(){
 DDD ddd;
 ddd.ShowString();
 return 0;
}


이경우를 살펴보자. 클래스 BBB와 CCC는 각각 클래스 AAA를 상속하고 있다.
그런가운데 우리의 DDD씨는 BBB와CCC의클래스를 상속하고 계시군요! ㅋ
자..그럼 생각해봅시다. BBB와 CCC클래스는 각각 AAA클래스를 상속하고 있으니 둘다
String1()이라는 함수를 가지고 있겠지..그런 B,C클래스를 상속한 D클래스는
String1()함수를 2개나 갖게 된다..그래서 메인함수에서 저렇게 호출을 해버리면
어떤 String1()을 호출해야할지를 몰라서..오류를 뿜어내고 만다..우어~~
그럴경우 B,C클래스에서 A를 상속할떄 virtual상속을 하면 되는데(virtual base클래스)
쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지마라쓰지

블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,