条款43:学习处理模板化基类内的名称

Know how to access names in templatized base classes.

类模板继承的问题:

class CompanyA {
public:
    ...
    void sendClearText(const std::string& msg);
    ...
};

class CompanyB {
public:
    ...
    void sendClearText(const std::string& msg);
    ...
};

class MsgInfo { ... }

template<typename Company>            // 基类
class MsgSender {
public:
    ...
    void sendClear(const MsgInfo& info) {
        std::string msg;
        Company c;
        c.sendClearText(msg);
    }
};

template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
    ...
    void sendClearMsg(const MsgInfo& info) {
        ...                 // 发送前操作;
        sendClear(info);    // 调用基类的发送实现,编译不通过;
        ...                 // 发送后操作;
    }
};

当编译器遇到 class template LoggingMsgSender 定义式时,并不知道它继承什么样的 class,因为 MsgSender<Company> 不到 class template LoggingMsgSender 被具现化出来时,是不知道 Company 的样子。也就是说编译器无法确定 sendClear 函数的具体实现,例如如果 MsgSender<Company> 存在一个特化版,它可能没有对应的 sendClear 函数:

template<>
class MsgSender<Company Z> {
public:
    ...
};

class 定义式前的 template<> 语法象征着这既不是 template 也不是标准的 class,而是一个特化版的模板类,在 template 实参为 CompanyZ 时被使用。

解决类模板继承问题的办法有三个:

  • 第一个是在 Base class 函数调用动作之前加上 this->

  • 第二个是使用 using 声明式;

  • 第三个是明白指出被调用函数位于 base class 内;

template<typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
    ...
    using MsgSender<Company>::sendClear;        // 第二种
    void sendClearMsg(const MsgInfo& info) {
        this->sendClear(info);                  // 第一种
        MsgSender<Company>::sendClear(info);    // 第三种
    }
};

Last updated

Was this helpful?