Class Templates 可以继承其他classes,也可以被其他classes继承。大多数情况下 class templates 和 non-templates classes 在这方面并没有什么重大差别。但是有一个微妙和重要的问题,出现在“由一个受控名称dependent name 所指涉的base class,衍生出一个class template”时,我们先从简单的non-dependent base classes说起。

1. 非受控的Non-dependent Base Classes

在class template中, 所谓non-template base classes 是指一个无需知道任何template argument就可以确定地类型。换句话说,用来指涉该base class的名称,是个非受控名称non-dependent name。例如:

template <typename X>

class Base{

public:

int basefield;

typedef int T;

};

class D1:public Base<Base<void> > {   //并不真正是个template

public:

void f() {basefield = 3; }      // 以通常方法继承来的成员

};

template <typename T>

class D2: public Base<double> { // non-dependent base class

public:

void f() {basefield = 7;}   // 以一般方法存取继承而来的成员

T strange;                    //T是Base<double>::T, 不是模板参数template parameters

};

non-dependent base templates的行为和常规的non-template base classes 非常相似,但是有个令人惊异的差异是:当编译器在derived class template中查询一个未受饰名称unqualified name时,会优先查询non-dependent base templates,然后才查询template parameters.这意味着上面例子中,class template D2的strange将拥有Base<double>::T类型(本例为int)。

因此以下函数语句非法:

void g(D2<int*> & d2, int* p)

{

d2.strange = p; // 错误,类型不匹配:trange是int, p 是int*

}

这与直觉相悖(感觉int*,就是模板实参传给了T),derived template 编写者因此特别留心其non-dependent bases中的名称,甚至是简介继承,或名称是private。较好的做法是把template parameters 放在被它们模板化的物体的作用域内。

2. 受控的Dependent base Classes

上面的例子中,base class是完全确定的。它不取决于某个template parameter。也就是说C++

编译器只要是见到template的定义,就可以在base classes中查询非受控名称。C++标准规定,编译器只要见到一个非受控名称non-dependent name,就立即开始查询lookup。

考虑下面的例子:

template <typename T>

class DD: public Base<T> {    //dependent base

public:

void f() {basefield = 0;}    //(1) have some problem...

};

template <>

class Base<bool> {                    //explicit specialization

enum { basefield = 42 };    // (2) a tricky

};

void g(DD<bool>& d)

{

d.f();                               //(3) oh,oh?

}

在(1)处我们发现,这里使用了一个非受控名称basefield:编译器一定会立即查询它。假设我们在template base中查询它,并将它系结为一个(在基类中找到的)int成员。然而之后,又立刻在(2)对这个泛型定义进行了特化,将basefield改成我们看到的枚举变量。于是当(3)处实例化DD:f的定义时,会发现(1)处对basefield的类型解释并不准确。

(2)处特化的DD<bool> 之中并没有可变化的basefield,因此编译器会报错。

为了解决这个问题,C++标准规定非受控名称non-dependent names不在受控的base class中查询。因此符合标准的C++编译器会在(1)处报错。欲修正上述程序代码,我们可以令basefield成为一个受控名称dependent name,而受控名称的查询过程会发生在它被实例化之后。此时basefield的特化类型就可以被编译器发现。例如,在(3)处,编译器会知道DD<bool>的base class是Base<bool>,而Base<bool>已被实例化。据此,我们可以修改程序代码如下:

//method 1

template <typename T>

class DD1: public Base<T> {

public:

void f() { this->basefield = 0;} //delay the lookup

};

另一种做法是使用一个受饰名称qualified name导入相依性(受控性,dependency)

//method2

template <typename T>

class DD2:public Base<T> {

public:

void f() { Base<T>::basefield = 0; }

};

如果觉得这么多修饰符号会弄乱程序代码,可用using声明语句将某个名称从受控的base class中带到当前作用域中,于是你就可以肆意使用它。

//method 1

template <typename T>

class DD3: public Base<T> {

public:

using Base<T>:: basefield; //(1) 现在,basefiled在当前域中为受控名称

void f() { basefield =0; }  //(2)正确

};

(2)进行的查询过程就会成功,它会找到(1)处的声明语句。

C++模板编程(16)---继承与类模板(Derivation and Class Templates)相关推荐

  1. C++知识点61——typename与class、模板编程与继承、模板类和友元、类模板与static成员

    一.typename与class的异同 1.啥时候既可以使用typename,又可以使用class? 当表示模板参数的时候,二者没有区别 2.啥时候只能使用typename,不能使用class? 当模 ...

  2. C++的类继承与类模板

    类继承是面向对象编程中很重要(也是很难)的内容,其能有效地提高代码复用水平,提高开发的效率. 目录 基本概念 公有继承 私有继承.保护继承 包含 多重继承 类模板 基本概念 继承的种类与特点 C++中 ...

  3. C++模板学习02(类模板)(类模板语法、类模板与函数模板的区别、类模板中的成员函数创建时机、类模板对象做函数参数、类模板与继承、类模板成员函数类外实现、类模板分文件编写、类模板与友元)

    C++引用详情(引用的基本语法,注意事项,做函数的参数以及引用的本质,常量引用) 函数高级C++(函数的默认参数,函数的占位参数,函数重载的基本语法以及注意事项) C++类和对象-封装(属性和行为作为 ...

  4. 类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

     1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPush ...

  5. 模板学习(2)----类模板

    类模板 模板的作用我们已经知道了,类模板的作用就是建立一个可以公用的类,这个类模板里面的成员及其数据类型不用制定,同样是由一个虚拟的类型来表示的.类模板中的数据成员以及成员函数的参数和返回值都可以进行 ...

  6. [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)

    http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1.  主版本模板类 首先我们来看一段初学者都能看 ...

  7. 类模板里面的函数写在类模板里面和写在类模板的外面,且在1个.cpp文件中

    和类一样,类模板里面声明的函数,其函数体写在类里面和外面都行,但是有一点需要注意:1.用友元函数重载<< 或 >>运算符,函数声明写在类模板里面,函数实现写在类模板外面,要在函 ...

  8. 第 16 章 string类和标准模板库

    第 16 章 string类和标准模板库 16.1 string类 C语言在 string.h(C++中为cstring)提供了一系列的字符串函数. 16.1.1 构造字符串 string 实际上是模 ...

  9. 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)

    0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...

最新文章

  1. 【转载】Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
  2. nginx + uwsgi + Django 应用部署
  3. 设置VMware随系统开机自动启动并引导虚拟机操作系统
  4. GIAC | 大数据分析系统在游戏领域的迭代与实践
  5. 网格自适应_Abaqus网格重划自适应技术
  6. centos8 yum太慢_Yum 慢到无法忍受?那是因为你没有这么做
  7. linux网络配置、ssh、scp及命令优先级作业
  8. 【毕业答辩】如何制作优秀的毕业论文答辩PPT?
  9. 使用RPM安装Mysql5.5找不到配置文件My.cnf
  10. 系统学习机器学习之线性判别式(三)--广义线性模型(Generalized Linear Models)
  11. Internet 的50年口述历史七.摩登时代上
  12. 【驱动】绿联usb转rs232串口(CR104)驱动
  13. web漏洞扫描器原理_基于指纹识别的漏洞扫描设计
  14. 企业微信API学习笔记
  15. c语言 可以得什么软件下载,用C语言的软件哪可以下载啊?
  16. Ubuntu虚拟机镜像下载及创建
  17. Fvuln-自动化web漏洞检测工具
  18. mysql 汉字笔画排序规则_SQL Server与MySQL中排序规则与字符集相关知识的一点总结...
  19. 2.7 zio入门——更多的Effect构造函数
  20. 手机版python3h如何自制游戏_Python 飞机大战|10 分钟学会用 python 写游戏

热门文章

  1. 1到100python加法_在1到9之间插入加减法乘除,计算结果等于100
  2. 如何做一个基于微信二手交易小程序系统毕业设计毕设作品
  3. 当前主流电脑的BIOS调出键
  4. 【复数表达】CNM: An Interpretable Complex-valued Network for Matching
  5. 基于django开发在线考试系统——(二)model模型设计
  6. 腾讯大数据安全体系(PPT)
  7. 有了开发板和平台资源,AI语音技能开发没有想象那么难
  8. Apache Nifi JoltTransformJSON JOLT 语法解析
  9. RobotFramework环境配置十七:数据驱动(Read Excel File)
  10. 2009-2010嵌入式调查报告