728x90
728x90
9-1 객체의 멤버 함수가 사실은 어디에 있는가
* 예제를 이해하기 위한 사전지식 : 함수포인터
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class A
{
int n;
public:
A(int n) {
this->n = n; // 인덱스 단원 - this포인터 복습
}
void add() {
n++; // n을 증가
}
};
int main()
{
A a1(10);
A a2(20);
a1.add();
a2.add();
return 0;
}
모든 a클래스 객체가 하나의 add함수를 공유 (코드 영역 안에 있는 add 함수를 공유한다.)
그렇지만 각각 객체의 n은 구분한다. 어떻게?
void add(A* a) { (a->n)++; }
이렇게 변경된다. 자기자신의 주소값 this를 인자값으로 전달한다...
9-2 가상 함수가 동작하는 원리
* 예제를 이해하기 위한 사전지식 : 가상함수 정의, 장점
class A
{
int a;
int b;
public:
virtual void fct1(){
cout<<"fct1(...)"<<endl; // 멤버함수는 코드영역으로 들어가 공유된다
}
virtual void fct2(){
// 클래스의 멤버함수 중 하나라도 virtual로 선언된 멤버함수가 있으면
// 그 클래스의 멤버함수 정보를 지니는 a 클래스 객체의 virtual 테이블이 생성된다.
// a 클래스 객체의 함수를 호출할 때마다 virtual 테이블을 참조하게 된다
// 위치에 대한 정보를 갖고 있다
cout<<"fct2(...)"<<endl;
}
};
class B : public A
{
int c;
int d;
public:
virtual void fct1(){ // 오버라이딩 + 재정의
cout<<"overriding fct1(...)"<<endl;
}
void fct3(){
cout<<"fct3(...)"<<endl;
}
};
클래스의 멤버함수 중 하나라도 virtual로 선언된 멤버함수가 있으면
그 클래스의 멤버함수 정보를 지니는 a 클래스 객체의 virtual 테이블이 생성된다.
a 클래스 객체의 함수를 호출할 때마다 virtual 테이블을 참조하게 된다
위치에 대한 정보를 갖고 있다
int main()
{
A a;
a.fct();
}
호출하러 들어오면 테이블의 키값을 찾는다
직접가는 게 아니라 거쳐가게 된다
virtual 테이블에 의해 전에 배웠던 기능이 구현되었던 것!
//은행 계좌 관리 프로그램 3
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class A
{
int a;
int b;
public:
virtual void fct1() {
cout << "fct1(...)" << endl; // 멤버함수는 코드영역으로 들어가 공유된다
}
virtual void fct2() {
// 클래스의 멤버함수 중 하나라도 virtual로 선언된 멤버함수가 있으면
// 그 클래스의 멤버함수 정보를 지니는 a 클래스 객체의 virtual 테이블이 생성된다.
// a 클래스 객체의 함수를 호출할 때마다 virtual 테이블을 참조하게 된다
// 위치에 대한 정보를 갖고 있다
cout << "fct2(...)" << endl;
}
};
class B : public A
{
int c;
int d;
public:
virtual void fct1() { // 오버라이딩 + 재정의
cout << "overriding fct1(...)" << endl;
}
void fct3() {
cout << "fct3(...)" << endl;
}
};
// 오버라이딩 된 virtual은 테이블에 정보가 없어서 호출이 되지 않는다
//
int main(void)
{
A* aaa = new A();
aaa->fct1();
B* bbb = new B();
bbb->fct1();
return 0;
}
가상함수 단점
메모리공간 소모
함수호출이 늦어진다
=> 그러나 장점이 훨씬 크다!
virtual 테이블의 개념까지 정리해보자
9-3 다중 상속에 대한 이해
다중상속 : 둘 이상의 클래스를 동시에 상속하는 것
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
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(void)
{
CCC ccc;
ccc.ShowString();
return 0;
}
9-4 다중 상속의 모호성
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
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(void)
{
CCC ccc;
ccc.ShowString();
return 0;
}
9-5 virtual base 클래스
//은행 계좌 관리 프로그램 3
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
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(void)
{
DDD ddd;
ddd.ShowString();
return 0;
}
virtual base 클래스
A 클래스 멤버를 하나만 포함할 수 있게 만든 것.
B와 C클래스가 A클래스를 virtual로 상속을 하면 D가 상속하는 A클래스는 한번만 상속되는 규칙
=> 웬만하면 사용을 피할 것.
//은행 계좌 관리 프로그램 3
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class AAA {
public:
void String1() {
cout << "AAA::String" << endl;
}
};
class BBB : virtual public AAA {
public:
void String2() {
cout << "BBB::String" << endl;
}
};
class CCC : virtual public AAA {
public:
void String3() {
cout << "CCC::String" << endl;
}
};
// virtual을 넣으면 A클래스를 한번만 상속하게 된다
class DDD : public BBB, public CCC //다중상속
{
public:
void ShowString() {
//CCC::String1();
String1();
String2();
String3();
}
};
int main(void)
{
DDD ddd;
ddd.ShowString();
return 0;
}
728x90
728x90
'C, C++ > 열혈 C++ 프로그래밍' 카테고리의 다른 글
[윤성우 열혈 c++] OOP 단계별 프로젝트 03단계 (0) | 2021.11.01 |
---|---|
[윤성우 열혈 c++] OOP 단계별 프로젝트 02단계 (0) | 2021.11.01 |
08.상속과 다형성 - 2. 가상함수 (0) | 2021.10.14 |
[윤성우 열혈 C++] 08.상속과 다형성 영상 (0) | 2021.10.12 |
08.상속과 다형성 - 1. 객체 포인터의 참조관계 (0) | 2021.10.08 |