《Effective C++》读书笔记 条款43:学习处理模板化基类的名称

假设我们需要发送信息到若干个不同的公司,每个公司发送的信息分为加密和不加密的两种类型。可以利用模板技术写发送信息的类

按照书上的例子,比如现有A、B两个公司,都支持发送普通消息和加密消息。MsgSender是一个模板类,在编译器根据要给哪个公司发送消息调用相应公司的函数。这个做法是可行的。

class CompanyA
{
public:
	void SendCleartext(const std::string& msg);
	void SendEncrypted(const std::string& msg);
};
class CompanyB
{
public:
	void SendCleartext(const std::string& msg);
	void SendEncrypted(const std::string& msg);
};
template<typename Company>
class MsgSender
{
public:
	void sendClear()
	{
		std::string msg;
		Company c;
		c.Sendcleartext(msg);
	}
	void sendSreect();
};

如果我们想多加一个功能,就是每次都记录一下发送了什么信息,我们可以用下面这个类

template<typename Company>
class LoggingMsgSender :public MsgSender <Company>
{
public:
	void SendClearMsg()
	{
		sendClear();
	}
};

但是sendClear();的调用可能会通不过编译(ps:我用的vs2008和vs2013都通过了编译。。。。这个和编译器有关),因为LoggingMsgSender继承的MsgSender<Company>中的Company是个Template参数,不到具现化时是不知道是什么的,而编译器考虑到可能会存在特化板的MsgSender template,不存在sendClear函数,所以就不能通过编译。比如只向公司Z发送加密的消息,不发送普通消息,为Z公司准备了一个特化的MsgSender template,不存在发送普通消息的函数。

class Companyz
{
public:
    void sendEncrypted(const std::string& msg);
};
template <>//表明是全特化的
class MsgSender < Companyz >
{
public:
    void sendClear();
};

如果这时候我们再用上面的可以添加日志的类,如果Company==Companyz,代码就不合法了,因为此时的基类MsgSender不存在sendClear函数。

所以C++,通常拒绝在模板化基类中寻找继承而来的名称(本例的sendClear)。通俗点说,就是在派生类中调用从模板化基类中继承而来的函数,因为这个函数可能不存在(特化的版本可能不存在这个函数)。

解决方式,向编译器承诺模板基类的任何特化版本都将支持其一般(泛化)版本所提供的接口。如果出现不支持一般版本所提供的接口的特化版本,还是会出现无法编译的情况。

1.在基类函数调用动作之前加上this->

this->sendClear();

2.使用using声明式

在调用之前 using MsgSender<Company>::senderClear;//也就是告诉编译器,请他假设sendClear位于基类中

3.明白指出被调函数位于基类中

MsgSender<Company>::sendClear();
 

请记住:

可在derived class template内通过“this->”指涉base class template内的成员名称,或借由一个明白写出的“base class资格修饰符”完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值