템플릿으로 만들어진 기본 클래스 접근하기(effective c++ 43)

2015. 8. 7. 14:24프로그래밍/Effective C++

728x90
728x90
템플릿 기본 클래스 호출 시 문제점
템플릿 기본 클래스의 함수를 호출하는데 템플릿 매개변수의 인스턴스가 무엇이 생성되는지 
알 수 없기 때문에 해당 함수를 찾지 못하는 문제점이 있다.

해결방안

기본 클래스 함수에 대한 호출문 앞에 this 키워드를 사용해 준다.


using 선언을 통해 기본 클래스의 이름을 파생 클래스의 유효범위로 끌어온다.


호출할 함수가 기본 클래스의 함수라는 점을 명시적으로 지정한다. (Base::)

- 이 방법은 추천하진 않는다.(명시적 한정으로 가상 함수일 경우 바인딩이 무시된다)


정리
파생 클래스 템플릿에서 기본 클래스 템플릿의 이름을 참조할 때는, this 접두사 붙이자.

또는 기본 클래스 한정문을 명시적으로 써 주자.

예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <string>
 
class CompanyA
{
public:
    CompanyA() { }
    ~CompanyA() { }
 
    void sendClearText(const std::string& msg) { }
 
private:
 
};
 
class CompanyB
{
public:
    CompanyB() { }
    ~CompanyB() { }
 
//    void sendClearText(const std::string& msg) { }
 
private:
 
};
 
class MsgInfo { };
 
template<typename Company>
class MsgSender
{
public:
    void sendClear(const MsgInfo& info)
    { 
        std::string msg;
 
        Company c;
        c.sendClearText(msg);
    }
};
 
// 컴파일러가 이 클래스 템플릿의 정의와 마주칠 때,
// 컴파일러는 이 클래스가 어디서 파생된 것인지를 모른다.
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
    // 첫번째 방법
    // 유효 범위를 끌어내 가져올 수 있다.
    using MsgSender<Company>::sendClear;
 
public:
    // 호출 안 되야함.
    void sendClearMsg(const MsgInfo& info)
    {
        // 메시지 전송 전 정보를 로그에 기록
 
        // 에러버전
        sendClear(info);
 
        // 해결하는 두 번째 방법
//        this->sendClear(info);
 
        // 세 번째 방법
        // 기본 클래스의 함수라는 것을 명시적으로 알려준다.
        // 이 방법은 그리 추천하는 방법은 아니다 : 호출되는 함수가 가상함수면 가상 함수 바인딩이 무시된다.
//        MsgSender<Company>::sendClear(info);
 
        // 메시지 전송 후 정보를 로그에 기록
    }
};
 
// visual studio 2012에서는 에러가 안난다.
// 왜 에러가 안나지?
 
// codepad에서 실행하면 다음과 같은 에러가 난다.
// t.cpp: In member function 'void LoggingMsgSender<Company>::sendClearMsg(const MsgInfo&)':
// Line 49: error: there are no arguments to 'sendClear' that depend on a template parameter, so a declaration of 'sendClear' must be available
// compilation terminated due to -Wfatal-errors.
 
 
int main()
{
    LoggingMsgSender<CompanyA> testA;
    LoggingMsgSender<CompanyB> testB;
    MsgInfo msg;
    testA.sendClearMsg(msg);
 
    // 호출하면 에러
    // testB.sendClearMsg(msg);
 
    return 0;
}
cs


728x90
반응형