항목 43 템플릿으로 만들어진 부모 클래스 안의 이름에 접근하는 방법을 알아두자
43.1 부모 클래스 템플릿
- 부모 템플릿 클래스를 상속받은 자식 클래스에서 부모 클래스에 있는 함수를 호출할 수 없다.
- T가 템플릿 매개변수이므로 인스턴스화하기 전까지 MsgSender<T> 클래스가 어떤 형태인지 알 수 없다.
- 즉, SendRaw 함수가 MsgSender<T>에 있는지 알 수 없으므로 컴파일 오류가 발생한다.
class CompanyA
{
public:
void SendRawText(const std::string& _strMsg) { ... }
void SendEncryptedText(const std::string& _strMsg) { ... }
};
class CompanyZ
{
public:
void SendEncryptedText(const std::string& _strMsg) {}
};
class MsgInfo { ... };
template<typename T>
class MsgSender
{
public:
void SendRaw(const MsgInfo& _oMsgInfo)
{
std::string strMsg = "";
T oCompany;
oCompany.SendRawText(strMsg);
}
void SendEncrypted(const MsgInfo& _oMsgInfo)
{
std::string strMsg = "";
T oCompany;
oCompany.SendEncryptedText(strMsg);
}
};
template<typename T>
class LogMsgSender : public MsgSender<T>
{
public:
void SendLogRawMsg(const MsgInfo& _oMsgInfo)
{
// C3861 'SendRaw': 식별자를 찾을 수 없습니다
SendRaw(_oMsgInfo);
}
};
- 완전 템플릿 특수화(total template specialization)
- 클래스 템플릿이 특정한 타입으로 특수화되었고 이때 템플릿 매개변수들이 완전히 특정한 타입으로 특수화된 경우를 말한다.
- 즉, T가 CompanyZ 타입인 경우, SendRaw 함수가 없다.
- 부모 클래스 템플릿이 특수화될 수 있기 때문에 컴파일러는 부모 템플릿 클래스에서 상속된 이름을 찾지 않는다.
// MsgSender 템플릿 클래스를 CompanyZ 타입으로 특수화합니다.
template<>
class MsgSender<CompanyZ>
{
public:
void SendEncrypted(const MsgInfo& _oMsgInfo)
{
std::string strMsg = "";
CompanyZ oCompany;
oCompany.SendEncryptedText(strMsg);
}
};
43.2 자식 클래스 템플릿에서 부모 클래스 템플릿 참조
- 자식 클래스 템플릿에서 부모 클래스 템플릿을 참조하는 세 가지 방법이 있다.
- 부모 클래스 함수를 호출하는 코드 앞에 this->를 작성한다.
- using 선언으로 부모 클래스의 이름을 자식 클래스의 유효 범위 안으로 확장한다.
- 부모 클래스 함수를 호출하는 코드 앞에 부모 클래스라는 것을 명시한다. 단, 가상 함수인 경우, 동적으로 바인드되지 않으므로 추천하지 않는다.
- 컴파일러는 자식 클래스 템플릿의 정의를 분석할 때(이른 진단), 자식 클래스 템플릿이 인스턴스화될 때(늦은 진단)로 나누어 부모 클래스 멤버에 대한 참조가 유효한지 판단한다.
template<typename T>
class LogMsgSender : public MsgSender<T>
{
public:
// 1. 컴파일러에게 부모 클래스에 SendRaw 함수가 있다고 가정하게 합니다.
using MsgSender<T>::SendRaw;
void SendLogRawMsg(const MsgInfo& _oMsgInfo)
{
// 2. 컴파일러에게 SendRaw 함수가 상속된 것으로 가정하게 합니다.
this->SendRaw(_oMsgInfo);
// 3. 컴파일러에게 SendRaw 함수가 상속된 것으로 가정하게 합니다.
MsgSender<T>::SendRaw(_oMsgInfo);
}
};
NOTE
① 자식 클래스 템플릿에서 부모 클래스 템플릿 안에 있는 이름을 참조하려면 this-> 접두사를 붙이거나 명시적으로 using 선언한다.
'Object Oriented Programming(C++) > Effective C++' 카테고리의 다른 글
Effective C++ | 항목 52 placement new를 작성한다면 placement delete도 작성하자 (0) | 2024.08.08 |
---|---|
Effective C++ | 항목 42 typename의 두 가지 의미를 제대로 파악하자 (0) | 2024.08.06 |
Effective C++ | 항목 41 템플릿 프로그래밍은 암시적 인터페이스와 컴파일 시간 다형성부터 (0) | 2024.08.06 |
Effective C++ | 항목 40 다중 상속은 심사숙고해서 사용하자 (0) | 2024.08.06 |
Effective C++ | 항목 39 private 상속은 심사숙고해서 구사하자 (0) | 2024.08.06 |
댓글