当前位置: 首页 > article >正文

C++学习笔记----11、模块、头文件及各种主题(一)---- 模板概览与类模板(8)

2.7、从类模板派生

        可以从类模板继承。如果派生类继承自模板自身,也必须是模板。还有别的选择,可以继承自类模板的特定实例,这种情况下继承类就不必为模板。还是前面的例子,假定你认为通用Grid类无法提供游戏面板足够的功能性。特别要提出的是,想要给游戏面板添加一个move()成员函数来将棋子从一个位置移动到面板的另一个位置。下面是GameBoard模板的类定义:

import grid;
import std;

export
template <typename T>
class GameBoard : public Grid<T>
{
public:
	// Inherit constructors from Grid<T>.
	using Grid<T>::Grid;

	void move(std::size_t xSrc, std::size_t ySrc, std::size_t xDest, std::size_t yDest);
};

        该GameBoard模板从Grid模板派生,因此继承了其所有的功能。不需要重写at(),getHeight(),或任何其他的成员函数。也不需要添加拷贝构造函数,operator=,或析构函数,因为在GameBoard中没有任何动态内存分配。还有,GameBoard显式从基类Grid<T>继承了构造函数。。

        继承的语法看起来是正常的,除了基类为Grid<T>,而不是Grid之外。这个语法的原因是GameBoard模板不是真的派生于通用的Grid模板。而是,每一个特定类型的GameBoard模板的实例继承自同样类型的Grid实例。例如,如果要用ChessPiece类型来初始化一个GameBoard,那么编译器也会生成Grid<ChessPiece>的代码。:public Grid<T>语法说明该类继承自任何Grid实例,对于T类型的参数都是合理的。

        下面是move()成员函数的实现:

template <typename T>
void GameBoard<T>::move(std::size_t xSrc, std::size_t ySrc, std::size_t xDest, std::size_t yDest)
{
	Grid<T>::at(xDest, yDest) = std::move(Grid<T>::at(xSrc, ySrc));
	Grid<T>::at(xSrc, ySrc).reset(); // Reset source cell
	// Or:
	// this->at(xDest, yDest) = std::move(this->at(xSrc, ySrc));
	// this->at(xSrc, ySrc).reset();
}

        注意:虽然有些编译器没有强化它,c++名字查找规则要求使用this指针或Grid<T>::在基类模板中来指向数据成员与成员函数。因此,我们使用Grid<T>::at()而不是简单的at()。

        可以使用GameBoard模板如下:

GameBoard<ChessPiece> chessboard { 8, 8 };
ChessPiece pawn;
chessBoard.at(0, 0) = pawn;
chessBoard.move(0, 0, 0, 1);

        注意:当然了,如果想要覆盖Grid的成员函数,就要在Grid类模板中把它们标识成virtual。

2.8、继承与特殊化

        有些程序员发现模板继承与模板特殊化之间的区别令人不解。下表总结了其不同:

继承

特殊化

重用代码?

是的:继承类包含了所有基类的数据成员与成员函数。

不是:必须重写所有的特殊化要求的代码。

重用名字?

不是:继承类的名字必须与基类名字不同。

是的:特殊化必须与原来的名字相同。

支持多态?

是的:继承类的对象可以代表基类的对象。

不是:模板的每一个实例类型是一个不同的类型。

        注意:继承用于扩展实现与多态。特殊化用于特定类型的客户化实现。

2.9、别名模板

        我们都了解类型别名与typedef的概念。它们允许对特定类型给出其它的名字。我们复习一下,例如,可以对int类型给另外一个名字,写出如下的类型别名:

using MyInt = int;

        类似地,可以用类型别名给类模板起另一个名字。假定你有如下的类模板:

template <typename T1, typename T2>
class MyClassTemplate { /* ... */ };

        可以定义如下的类型别名,指定两个类模板类型参数:

using OtherName = MyClassTemplate<int, double>;

        也可以使用typedef而不是这样的类型别名。

        还有,也可以只指定一些类型而保持模板类型参数中的其它类型不变。这叫做别名模板。下面为示例:

template <typename T1>
using OtherName = MyClassTemplate<T1, double>;

        在这种情况下,就不能使用typedef了。


http://www.kler.cn/a/392248.html

相关文章:

  • 计算机网络(3)网络拓扑和IP地址,MAC地址,端口地址详解
  • 第74期 | GPTSecurity周报
  • 【秋招笔试-支持在线评测】11.13花子秋招(已改编)-三语言题解
  • ISAAC SIM踩坑记录--ubuntu 22.04操作系统安装
  • 使用支付宝沙箱完成商品下单
  • 解决:WSL2可视化opencv和pyqt冲突:QObject::moveToThread
  • 深度学习-神经网络基础-激活函数与参数初始化(weight, bias)
  • [Linux]:IO多路转接之epoll
  • 鸿蒙next版开发:订阅应用事件(ArkTS)
  • EasyExcel 使用多线程按顺序导出数据
  • linux GPIO
  • 【Linux】进程状态与进程优先级
  • torch jit 动态获取buffer
  • upload-labs通关练习
  • 闲鱼监控助手货源获取技巧(轻松找到优质货源的方法)
  • 【大数据测试spark+kafka-详细教程(附带实例)】
  • Unity3D设置3D物体不超出相机视角范围(物体一直保持在相机视角范围内)
  • Android S长按文件或视频或编辑中文字或输入框中文字不会弹出分享菜单
  • 零基础入门转录组下游分析——预后模型之多因素cox模型
  • 小西作业1_third order plant(SPM)
  • Linux也有百度云喔~
  • 在Java中使用ModelMapper简化Shapefile属性转JavaBean实战
  • 信令服务器设计之websocket基础
  • BERT配置详解1:构建强大的自然语言处理模型
  • 【Echarts图轮播显示label】
  • PHP动物收容所管理系统-计算机设计毕业源码94164