Regarding calling functions in base class, there is a difference between how non-template polymorphism and template polymorphism. This is because we have total template specialization in template world which will confuse compiler unless we are specific about it. Let me show you an example
voidsendSecret(const std::string& msg){ Company c; c.sendEncrypted(msg); } };
template<typename Company> classLoggingMsgSender: public MsgSender<Company> { public: using MsgSender<Company>::sendClear; voidsendClearMsg(const std::string& msg) { //write "before sending" info to the log; sendClear(msg); // <-------- won't compile! //write "after sending" info to the log; } };
You might be surprised that calling sendClear won’t compile. There is a reason compiler gives you this error. Imagine you also have following code
Where CompanyC doesn’t have sendCleartext method and a total template specialization version of the class MsgSender for CompanyC which doesn’t have sendClear method. Now you will appreciate your compiler thinking ahead of you previously because now it really doesn’t make sense to compile!
There are three ways to tell compiler that please assume sendClear always exists.
// This is not preferred because if the function being called is virtual, // explicit qualification turns off the virtual binding behavior. template<typename Company> classLoggingMsgSender: public MsgSender<Company> { public: voidsendClearMsg(const std::string& msg) { MsgSender<Company>::sendClear(msg); } };
You can argue that compiler can detect this in two places
when derived class template definitions are parsed
when those templates are instantiated with specific template arguments You are correct. But C++’s policy is to prefer early diagnoses, and that’s why it assumes it knows nothing about the contents of base classes when those classes are instantiated from templates.