2. Base From Member Idiom
우선 Idiom이 무엇인지 부터 알아보자
C++ Idiom
프로그래밍시 발생하는 문제를 해결하기 위한 기법.
C++의 언어적인 특성에 기반한 팁 문제해결 패턴이다.
(https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms)
이 수많은 Idiom 중에 Base From Member Idiom 을 알아보자 (나머지는 추후 업로드 하거나 안하거나 미래의 나만 알 것 같다...)
Base From Member Idiom
#include <iostream>
class KObject
{
public:
KObject()
{
m_iInitialized = 99;
}
int GetInitialized() const
{
return m_iInitialized;
}
private:
int m_iInitialized;
};
class KBase
{
public:
KBase(KObject& obj)
{
std::cout << obj.GetInitialized() << std::endl;
}
};
class KDerived1 : public KBase
{
public:
KDerived1() : KBase(m_object)
{
}
private:
KObject m_object;
};
int main()
{
KDerived1 d1;
}
위에 Idiom을 알아보기 위한 코드이다.
d1을 생성하게 되면 어떤 값이 출력이 될까? 99가 출력이 될까?
예상과는 다르게 쓰레기 값이 출력이 된다.
음... 무슨 문제일까
문제는
class KDerived1 : public KBase
{
public:
KDerived1() : KBase(m_object)
{
}
private:
KObject m_object;
};
이 KDerived1 생성자 이다.
KDerived1의 m_object의 메모리를 할당 받고 생성자를 호출하기 전에 KBase의 생성자가 호출이 된다.
따라서
KBase(KObject& obj)
{
std::cout << obj.GetInitialized() << std::endl;
}
이 부분에서 obj는 생성자가 호출이 안된 객체로 메모리만 할당돼 있는 상태이기 때문에 99가 출력이 안되고 쓰레기값이 출력이 된다.
어떤 방법으로 이 문제를 해결할 수 있을까?
해결
struct PrivateBase
{
KObject m_object;
};
class KDerived2 : protected PrivateBase, public KBase
{
public:
KDerived2() : KBase(m_object)
{
}
};
이런식으로 두가지를 상속받는 방법으로 해결이 가능하다. C++에서 두개 이상 상속을 받는것은 위험한 방법이지만, 기능 추가를 위해 받는 방법은 종종 사용한다고 한다.
protected PrivateBase, public KBase 이렇게 돼있다면 순서대로 PrivateBase, KBase 순으로 상속이 진행 된다.
따라서 PrivateBase의 m_object가 먼저 생성이 되고, KBase가 생성이 되면서 위에 문제를 해결할 수 있게 된다.
#include <iostream>
class KObject
{
public:
KObject()
{
m_iInitialized = 99;
}
int GetInitialized() const
{
return m_iInitialized;
}
private:
int m_iInitialized;
};
class KBase
{
public:
KBase(KObject& obj)
{
std::cout << obj.GetInitialized() << std::endl;
}
};
class KDerived1 : public KBase
{
public:
KDerived1() : KBase(m_object)
{
}
private:
KObject m_object;
};
struct PrivateBase
{
KObject m_object;
};
class KDerived2 : protected PrivateBase, public KBase
{
public:
KDerived2() : KBase(m_object)
{
}
};
int main()
{
KDerived1 d1;
KDerived2 d2;
}
KDerived1 과는 다르게 KDerived2에서는 99를 출력 하게 된다.