시작은 미미하나 끝은 쥬쥬하리라.

Study/Passionate C++ Programming

[열혈 C++ 프로그래밍] (9) 가상의 원리와 다중상속

코딩뚜벅이 2024. 1. 24. 21:39

가상의 원리와 다중상속

  • 멤버함수와 가상함수
  • 다중상속

멤버함수와 가상함수

멤버 함수

물리적으로 메모리의 한 공간에 별도로 위치하여 함수가 정의된 클래스의 모든 객체가 메모리를 공유하는 형태
-> 논리적으로는 객체 안에 멤버 함수 존재
멤버 객체 객체가 생성되면 멤버 객체는 객체 메모리 공간

 

 

멤버 객체

객체가 생성되면 멤버 객체는 객체 메모리 공간 내부에 생성

 

 

가상함수 동작원리

1. 가상함수가 멤버로 포함
2. 가상함수 V-Table이 생성
3. 함수를 호출하는 경우 V-Table을 참조
-> 가상함수 테이블을 클래스별로 생성 : A클래스 테이블에는 B클래스 가상함수 정보가 없음
-> 가상함수 오버라이딩의 경우 유도 클래스의 V-Table에서 기초 클래스의 가상함수가 가려짐
-> 기초 클래스의 가상 함수가 가려졌으므로 유도 클래스의 가상 함수를 호출하는 내부 동작 구조

 

class A { virtual void Func1() { . . . } virtual void Func2() { . . . } }
class B { virtual void Func1() { . . . } virtual void Func3() { . . . } }


-> A클래스의 V-Table에는 A::Func1(), A::Func2()가 존재
-> B클래스의 V-Table에는 B::Func1(), A::Func2(), B::Func3()가 존재
-> B의 V-Table에는 가상함수 Func1()이 오버라이딩 되어 A클래스 함수가 가려짐
-> A클래스에서 Func1()을 호출하게 되면 B클래스의 Func1()함수가 호출

 


 

다중상속

다중상속

둘 이상의 클래스를 상속하는 형태
-> 유도 클래스의 객체는 모든 기초 클래스 멤버를 포함
다중 상속을 받는 유도 클래스에서 부모 클래스의 함수를 호출한다면 호출 대상의 파악이 불가하여 동작X
-> 가상 상속을 통해 임시 해결을 할 수 있음

 

 

가상상속

다중 상속에서 다이아몬드 구조를 띄게 되는 경우 데이터의 중복과 불피요한 생성자 호출을 막기 위해 사용

 

 

 

 

- A클래스 생성자와 소멸자 호출이 2번 발생
- int A_num에 접근을 시도하면 에러 발생
- B::A_num or C::A_num을 통해 접근해야 함
-> virtual을 통해 문제 해결 가능

 

 

 

- virtual 키워드를 통해 위 문제 해결
- 불필요한 생성자와 소멸자의 호출 해결
- 메모리의 크기가 증가
- 가상 상속 시 vbptr이라는 offset을 가리키는 포인터가 생성되며 virtaul로 상속된 클래스는 메모리 구조에서 제일 아래에 위치
-> 다중 상속으로 인한 가상 상속은 데이터 증가와 성능 저하를 야기