C/C++编程:派生和类模板

1060 篇文章 300 订阅

类模板可以继承也可以被继承。一般模板和非目标的继承没有什么区别。然而,要从依赖型名称所引用的基类派生一个类模版的情况下,这两者之间有一个重要的区别。让我们来看个例子

非依赖型基类

在一个类模板中,一个非依赖型基类是指:无需知道模板实参就可以完全确定类型的基类。也就是说,基类名称是用非依赖型名称来表示的。

template<typename X>
class Base{
public:
    int basefield;
    typedef int  T;
};

class D1 : public Base<Base<void>>{  // 实际上不是模板
public:
    void f(){ basefield = 3;}
};

template<typename T>
class D2 : public Base<double>{  // 非依赖型基类
public:
    void f(){ basefield = 7;}  //  正常访问继承成员。 
    T strange;                     //T 是Base<double>::T, 而不是模板参数
};

模板中的非依赖型基类和普通非模板类中的基类的区别在于:对于模板中的非依赖型基类而言,如果在它的派生类中查找一个非受限名称,那么就会先查找这个非依赖型基类,然后才查找模板参数列表。也就是说,下面是错的:

void g(D2<int *> & d2, int *p){
    d2.strange = p;  // 错误,类型不匹配
}

依赖型基类

C++标准规定:

  • 对于模板中的非依赖型名称,将会在看到的第一时间查找
  • 非依赖型名称不会在依赖型基类中进行查找
template<typename X>
class Base{
public:
    int basefield;
    typedef int  T;
};

template<typename T>
class DD : public Base<T>{
public:
    void f() { basefield = 0};  //error
};

修改方案:

  • 方案1:让basefield也成为依赖型名称(推荐)。 依赖型名称只有在实例化是才会进行查找,而且实例化时,基类的特化是已知的
template<typename X>
class Base{
public:
    int basefield;
    typedef int  T;
};

template<typename T>
class DD : public Base<T>{
public:
    void f() { this->basefield = 0; };  //依赖型名称,查找被延迟了
};

  • 方案2:利用受限名称来引入依赖性。
template<typename T>
class DD : public Base<T>{
public:
    void f() { Base<T>::basefield = 0; };  //(1)非依赖型名称
};

但是方案2有一个缺点:如果原来的非受限的非依赖型名称是被用于虚函数调用的话,那么这种引入依赖性的限定将会禁止虚函数调用,从而也会改变程序的含义。因此,但方案2不合适时请用方案1

template<typename X>
class B{
public:
    enum E{e1 = 6, e2 = 28, e3 = 496};
    virtual void zero(E e = e1);
    virtual void one(E&);
};

template<typename T>
class D : public B<T>{
public:
    void f(){
        typename D<T>::E e;  // this->E会是一个无效的调用
        this->zero();   //D<T>::zero()会禁止虚函数调用
        one(e);             //one是一个依赖性名称,因为它的实参是依赖型的
    }
};

建议:允许使用this->前缀的地方都使用this->

  • 方案3: 不断重复的限定也能会使得代码不好看,这时可以在派生类中引入依赖性基类
template<typename T>
class D : public Base<T>{
public:
    using  Base<T>::basefield;
    void f(){ basefield = 0;}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值