effective c++ 43-处理模板化基类的名称
该节主要分析了一个写模板时常常会遇到的一个编译错误。
分析
这里有一个模板基类,有派生类继承了模板基类,并调用了基类中的方法,但是编译器却会报找不该方法,这是怎么回事?
#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
函数呢? 不是就定义在模板基类中吗?
实际上原因就是基类是一个模板类, 而模板类是可以被特化的,例如这里又有了一个CompanyZ
,而MsgSender对于CompanyZ的特化版本可能就没有sendClear
方法,因此编译器才会说sendClear
含义不明确。
class CompanyZ
{
public:
void sendEncrypted(const std::string& msg) {}
};
template<>
class MsgSender<CompanyZ>
{
public:
void sendSecret(const MsgInfo& info)
{
}
};
好了,知道了原因之后,那么就可以给出解决办法了,其实上面编译器也已经给出来一种办法。
第一种就是在派生类中调用模板基类中的方法时加上this->
。
template<typename Company>
class LoggingMsgSender : public MsgSender<Company>
{
public:
void sendClearMsg(const MsgInfo& info)
{
this->sendClear(info);
}
};
have a try
第二种就是在派生类中调用模板基类中的方法时加上使用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)
。文章来源:https://www.toymoban.com/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文章来源地址https://www.toymoban.com/news/detail-435096.html
总结
- 在派生类模板中如果需要调用模板基类的方法,需要使用this->,或者明确指出名称。
到了这里,关于effective c++ 43-处理模板化基类的名称 笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!