effective c++ 43-處理模板化基類的名稱
該節(jié)主要分析了一個寫模板時常常會遇到的一個編譯錯誤。
分析
這里有一個模板基類,有派生類繼承了模板基類,并調(diào)用了基類中的方法,但是編譯器卻會報找不該方法,這是怎么回事?
#include <string>
#include <iostream>
class CompanyA
{
public:
void sendCleartext(const std::string& msg)
{
std::cout << "A sendCleartext" << std::endl;
}
void sendEncrypted(const std::string& msg)
{
std::cout << "A sendEncrypted" << std::endl;
}
};
class CompanyB
{
public:
void sendCleartext(const std::string& msg)
{
std::cout << "B sendCleartext" << std::endl;
}
void sendEncrypted(const std::string& msg)
{
std::cout << "B sendEncrypted" << std::endl;
}
};
class MsgInfo {
public:
MsgInfo(std::string msg):msg_(msg){}
private:
std::string msg_{};
};
template<typename Company>
class MsgSender
{
public:
void sendClear(const MsgInfo& info)
{
std::string msg;
Company c;
c.sendCleartext(msg);
}
void sendSecret(const MsgInfo& info)
{
}
};
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void sendClearMsg(const MsgInfo& info)
{
sendClear(info);
}
};
int main()
{
MsgInfo info("test");
LoggingMsgSender<CompanyB> loggingMsgSender;
loggingMsgSender.sendClearMsg(info);
}
編譯輸出如下:
/home/work/cpp_proj/test2/main.cpp: In member function ‘void LoggingMsgSender<Company>::sendClearMsg(const MsgInfo&)’:
/home/work/cpp_proj/test2/main.cpp:63:9: error: there are no arguments to ‘sendClear’ that depend on a template parameter, so a declaration of ‘sendClear’ must be available [-fpermissive]
sendClear(info);
^~~~~~~~~
/home/work/cpp_proj/test2/main.cpp:63:9: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
/home/work/cpp_proj/test2/main.cpp: In instantiation of ‘void LoggingMsgSender<Company>::sendClearMsg(const MsgInfo&) [with Company = CompanyB]’:
/home/work/cpp_proj/test2/main.cpp:71:39: required from here
/home/work/cpp_proj/test2/main.cpp:63:18: error: ‘sendClear’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
sendClear(info);
~~~~~~~~~^~~~~~
/home/work/cpp_proj/test2/main.cpp:63:18: note: declarations in dependent base ‘MsgSender<CompanyB>’ are not found by unqualified lookup
/home/work/cpp_proj/test2/main.cpp:63:18: note: use ‘this->sendClear’ instead
從編譯的輸出也可以看出,原因是編譯器覺得sendClear
含義不明確,編譯器也給出了解決辦法,使用this->sendClear
,這里我們要思考的是,為什么編譯器會找不到sendClear
函數(shù)呢? 不是就定義在模板基類中嗎?
實際上原因就是基類是一個模板類, 而模板類是可以被特化的,例如這里又有了一個CompanyZ
,而MsgSender對于CompanyZ的特化版本可能就沒有sendClear
方法,因此編譯器才會說sendClear
含義不明確。
class CompanyZ
{
public:
void sendEncrypted(const std::string& msg) {}
};
template<>
class MsgSender<CompanyZ>
{
public:
void sendSecret(const MsgInfo& info)
{
}
};
好了,知道了原因之后,那么就可以給出解決辦法了,其實上面編譯器也已經(jīng)給出來一種辦法。
第一種就是在派生類中調(diào)用模板基類中的方法時加上this->
。
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void sendClearMsg(const MsgInfo& info)
{
this->sendClear(info);
}
};
have a try
第二種就是在派生類中調(diào)用模板基類中的方法時加上使用using
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
using MsgSender<Company>::sendClear;
public:
void sendClearMsg(const MsgInfo& info)
{
sendClear(info);
}
};
have a try
第三種就是在派生類中明確指出使用MsgSender<Company>::sendClear(info)
。文章來源:http://www.zghlxwxcb.cn/news/detail-435096.html
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void sendClearMsg(const MsgInfo& info)
{
MsgSender<Company>::sendClear(info);
}
};
have a try文章來源地址http://www.zghlxwxcb.cn/news/detail-435096.html
總結(jié)
- 在派生類模板中如果需要調(diào)用模板基類的方法,需要使用this->,或者明確指出名稱。
到了這里,關(guān)于effective c++ 43-處理模板化基類的名稱 筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!