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
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,

v