Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 28 | 29 | 30 |
Tags
- 파이썬
- Scala
- 백엔드
- hacking
- BOF
- BOF 원정대
- ChatGPT
- c
- 웹해킹
- c++
- 경제
- Javascript
- mysql
- Shellcode
- 딥러닝
- deep learning
- 리눅스
- 챗GPT
- Web
- 러닝스칼라
- Linux
- Python
- php
- hackerschool
- backend
- flask
- 인공지능
- webhacking
- hackthissite
- 러닝 스칼라
Archives
- Today
- Total
jam 블로그
[C++] 009. virtual의 원리와 다중 상속 본문
728x90
I. 클래스의 멤버 함수는 사실 어디에
- #include <iostream>
- using namespace std;
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();
return 0;
}
- 구조체와 전역 함수로 위의 클래스를 흉내내 보자
- #include <iostream>
- using namespace std;
- struct Data
{
int data;
void (*ShowData)(Data*);
void (*Add)(Data*,int);
}; - void ShowData(Data* THIS)
{
cout<<"Data : "<<THIS->data<<endl;
}
void Add(Data* THIS,int num)
{
THIS->data += num;
} - int main()
{
Data ddd1 = {10,ShowData,Add}; - ddd1.Add(&ddd1,10);
- ddd1.ShowData(&ddd1);
- Data ddd2 = {1,ShowData,Add};
ddd2.Add(&ddd2,1);
ddd2.ShowData(&ddd2);
return 0;
}
- 위의 소스를 실행하면 알수 있듯이 객체가 생성되면, 멤버 변수는 객체내에 존재하게된다. 그러나 멤버 함수는 메모리의 한 공간에 존재하면서, 모든 객체가 공유하는 형태를 취하게 된다.
II. 가상 함수가 동작하는 원리
- #include <iostream>
- using namespace std;
- 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;
}
가상 함수가 하나 이상 있을 시 컴파일러는 가상함수 테이블이라는 것을 만들어 둔다.
- 가상함수 테이블에서는 오버라이딩된 클래스의 가상 함수 fct1에 대한 정보는 포함되어있지 않다.
- 즉, 하나 이상의 가상함수를 멤버로 지니는 클래스의 객체에는 가상함수테이블을 위한 포인터가 멤버로 추가된다.
III. 다중 상속에 대한 이해
다중 상속이란
- 하나의 상속받는 클래스가 둘 이상의 기본 클래스를 상속하는 것을 말한다.
- #include <iostream>
- using namespace std;
- 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를 둘다 상속 받았기 때문에 String1과 String2를 호출 할수 있다.
IV. 다중 상속의 모호성
- #include <iostream>
- using namespace std;
- class AAA
{
public:
void String()
{
cout<<"AAA:String1"<<endl;
}
}; - class BBB
{
public:
void String()
{
cout<<"BBB:String2"<<endl;
}
}; - class CCC:public AAA,public BBB
{
public:
void ShowString()
{
String();
String();
}
};
int main()
{
CCC ccc;
ccc.ShowString();
return 0;
}
위와 같은 경우 오류가 나는데 AAA에서나 BBB에서 String이라는 함수를 썼기 때문이다.
- 따라서 ShowString에서 AAA::String, BBB::String 이런식으로 바꾸어 주어야 한다.
V. virtual Base 클래스
- #include <iostream>
- using namespace std;
class AAA
{
public:
void String1()
{
cout<<"AAA::String"<<endl;
}
};- class BBB:public AAA
{
public:
void String2()
{
cout<<"BBB::String"<<endl;
}
}; - class CCC : public AAA
{
public:
void String3()
{
cout<<"CCC::String"<<endl;
}
}; - class DDD:public BBB,public CCC
{
public:
void ShowString()
{
String1();
String2();
String3();
}
}; - int main()
{
DDD ddd;
ddd.ShowString();
return 0;
}
위의 소스를 컴파일 하면 String1에서 오류가 난다.
- 이유는 DDD에서 String1을 호출 하려고 하지만 상속받은 BBB를 참조해야할지 CCC를 참조해야할지 애매해서 오류가 난다.
- class BBB:virtual public AAA
{
public:
void String2()
{
cout<<"BBB::String"<<endl;
}
}; - class CCC : virtual public AAA
{
public:
void String3()
{
cout<<"CCC::String"<<endl;
}
};
- 이런식으로 AAA를 virtual로 상속 받으면 된다. 따라서 AAA클래스 안에 존재하는 멤버는 한번만 상속받게 된다.
'개발 및 관련 자료 > C' 카테고리의 다른 글
[C++] 011. string 클래스 디자인 (0) | 2013.05.12 |
---|---|
[C++] 010. 연산자 오버로딩 (0) | 2013.05.12 |
[C++] 008. 상속과 다형성 (0) | 2013.05.12 |
[C++] 007. 상속(Inheritance)의 이해 (0) | 2013.05.12 |
[C++] 006. static 멤버와 const 멤버 (0) | 2013.05.12 |
Comments