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);
...
};
... // classes for other companies
class MsgInfo { ... }; // class for holding information
// used to create a message
template
class MsgSender {
public:
... // ctors, dtor, etc.
void sendClear(const MsgInfo& info)
{
std::string msg;
create msg from info;
Company c;
c.sendCleartext(msg);
}
void sendSecret(const MsgInfo& info) // similar to sendClear, except
{ ... } // calls c.sendEncrypted
};
template
class LoggingMsgSender: public MsgSender{
public:
... // ctors, dtor, etc.
void sendClearMsg(const MsgInfo& info)
{
write "before sending" info to the log;
sendClear(info); // call base class function;
// this code will not compile!
write "after sending" info to the log;
}
...
};
注重 derived class(派生类)中的 message-sending function(消息发送函数)的名字 (sendClearMsg) 与它的 base class(基类)中的那个(在那里,它被称为 sendClear)不同。这是一个好的设计,因为它避开了 hiding inherited names(隐藏继续来的名字)的问题(参见《C++箴言:避免覆盖通过继续得到的名字》)和重定义一个 inherited non-virtual function(继续来的非虚拟函数)的与生俱来的问题(参见《C++箴言:绝不重定义继续的非虚拟函数》)。但是上面的代码不能通过编译,至少在符合标准的编译器上不能。这样的编译器会抱怨 sendClear 不存在。我们可以看见 sendClear 就在 base class(基类)中,但编译器不会到那里去寻找它。我们有必要理解这是为什么。class CompanyZ { // this class offers no
public: // sendCleartext function
...
void sendEncrypted(const std::string& msg);
...
};
template<>// a total specialization of
class MsgSender{ // MsgSender; the same as the
public: // general template, except
... // sendCleartext is omitted
void sendSecret(const MsgInfo& info)
{ ... }
};
template
class LoggingMsgSender: public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info)
{
write "before sending" info to the log;
sendClear(info); // if Company == CompanyZ,
// this function doesn't exist!
write "after sending" info to the log;
}
...
};
template
class LoggingMsgSender: public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info)
{
write "before sending" info to the log;
this->sendClear(info); // okay, assumes that
// sendClear will be inherited
write "after sending" info to the log;
}
...
};
template
class LoggingMsgSender: public MsgSender{
public:
using MsgSender::sendClear; // tell compilers to assume
... // that sendClear is in the
// base class
void sendClearMsg(const MsgInfo& info)
{
...
sendClear(info); // okay, assumes that
... // sendClear will be inherited
}
...
};
template
class LoggingMsgSender: public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info)
{
...
MsgSender::sendClear(info); // okay, assumes that
... // sendClear will be
} // inherited
...
};
LoggingMsgSenderzMsgSender;
MsgInfo msgData;
... // put info in msgData
zMsgSender.sendClearMsg(msgData); // error! won't compile
新闻热点
疑难解答