보통은 자식 클래스가 자신의 부모 클래스의 생성자만 호출 가능하고, 할아버지 클래스의 생성자를
호출 할 수 없지만, 가상 기반 클래스 에서는 예외가 있습니다...
즉, 손자 클래스가 자신의 부모보다도 상위인 할아버지 클래스의 생성자를 호출 할 수
있다는 점이죠...
또한, 이 경우에 있어서는 중간 클래스를 의미하는 부모 클래스(class XY, class XZ) 에서는 비록...
최상위 클래스의 생성자를 호출하는 코드인 CPointX(a) 가 XY, XZ 클래스의 생성자 초기화 리스트에
있지만, 손자 클래스인 XYZ 클래스의 생성자 초기화 리스트 부분에서...단 "한 번만" 호출된다는
점 입니다...
브레이크 포인트를 걸어서 코드 흐름을 추적해 보면 알겠지만, 위 코드에선 CPointX(a) 부분이 한 번 밖에
호출되지 않고, 이를 담당하는 것은 손자 클래스인 XYZ 클래스 입니다...
정리하면,,,가상 기반 상속에서는 손자 클래스에서 할아버지 클래스의 생성자를 직접 호출한다는
점이고, 중간 클래스인 부모 클래스에서는 비록, 그 상위 클래스의 생성자를 호출하는 코드가
있다고 하더라도 호출되지 않는다는 점 입니다...
또한...가상 상속을 사용하는 이유는 할아버지 클래스인 X 클래스를 상속받는 XY, XZ 클래스를 XYZ 라는
클래스가 상속받기 때문에...XYZ 입장에서는 X 클래스의 멤버가 어디에서 온 멤버인지 모호하기 때문에
이 가상상속을 사용하여, 모호함을 없애는 것입니다...
X X
| |
XY XZ
XY, XZ 를 상속받는 XYZ 클래스는 X의 멤버를 참조할 때 XY 에서 온 X인지, XZ 에서 온 X인지
모호함으로 인해 판단하기 어렵다는 점입니다...
그래서...이를 해결하고자 가상상속을 사용하는 것이고, 손자 클래스가 할아버지 클래스의 생성을
직접 담당하는 것입니다...
코드를 다음과 같이 수정 합니다...
class CPointXY : virtual public CPointX{
.....
// CPointX(a) 생성자는 여기에서 호출되지 않는다.
CPointXY(int a, int b) : CPointX(a), y(b)
};
class CPointXZ : virtual public CPointX{
.....
// CPointX(a) 생성자는 여기에서 호출되지 않는다.
CPointXZ(int a, int c) : CPointX(a),z(c)
};
class CPointXYZ : public CPointXY, public CPointXZ{
...
// 할아버지 클래스의 생성자를 직접 호출한다
// 만약, CPointX(a) 를 명시적으로 호출하는 코드가 없다면 할아버지 클래스인
// CPointX 클래스에 인자를 가지지 않는 디폴트 생성자가 있어야 합니다...
CPointXYZ(int a, int b, int c) : CPointX(a), CPointXY(a,b), CPointXZ(a,c), xyz(0)
...
};
출처 :
'프로그래밍(Programming) > c++, 11, 14 , 17, 20' 카테고리의 다른 글
포인터와 const (0) | 2012.11.01 |
---|---|
객체 지향과 영어표기&주석 (0) | 2012.10.31 |
void 형변환에 관하여 %p (0) | 2012.10.31 |
상속, 포함관계 의 생성자 소멸자 호출 관계. (0) | 2012.10.31 |
랜덤함수와 씨드값 (0) | 2012.10.31 |