C++-16 多态版扑克牌游戏

16 多态版扑克牌游戏

16.1 多种牌墩
皮纳克尔牌墩:只使用9到A的牌,但要使用两副牌
这个牌只要48张牌,牌24到47重复牌0到23 的牌点和花色

class PinochleDeck {
public:
	PinochleDeck();
	Card deal_a_card();
private:
	int cards[48];
	int nCard;
	void shuffle();
};

PinochleDeck::PinochleDeck() {
	srand(time(nullptr));
	for (int i =0; i < 48; ++i) {
		cards[i] = i;
	}
	shuffle();
}

void PinochleDeck::shuffle() {
	nCard = 0;
	for (int i = 47; i > 0; --i) {
		/*
		int j = rand() % (i + 1);
		swap(cards[i], cards[j]); */
		random_shuffle(cards, cards + 48);
	}
}

Card PinochleDeck::deal_a_card() {
	if (nCard > 47) {
		cout << endl << "正在重新洗牌..." << endl;
		shuffle();
	}
	int r = (cards[nCard] % 6)+7; //r=9-A
	//牌墩分为一半(%24)再除以6来生成0-3的花色
	int s = (cards[nCard++]%24) / 6;
	return Card(r, s);
}

在运行时切换牌墩
将my_deck声明为多个类的对象,为每个牌墩都创建一个对象,即使只使用其中一种类型——麻烦,浪费资源!

多态
在调用函数时,能自动调用当前对象的对应实现,即使实现不知道确定的类型
如果一个函数时多态的,那么总是能在运行调用该函数的正确版本

C++支持多态函数,必须无条件满足两个前提条件

  1. 涉及的类必须通过继承来关联,一个必须从另一个派生,或者都从一个通用基类派生
  2. 函数必须在基类中声明为virtual

派生类自动继承基类的所有成员,无法访问基类的私有成员
第三种访问级别protected:为所有的派生类(包括派生类的派生类)赋予访问权限

任何由派生类重写(override)的函数必须声明为virtual
构造函数不能为虚

实现多态性的;另一种方式是从一个通用基类(或成为“接口”)派生出各种牌墩类。作为抽象类的接口不能实例化,但可将一个派生类型的对象的地址传给一个基类型的指针:1. 创建对象,2. 获取他的地址,3. 将地址传给一个指针

Ideck *pDeck; //指向基类型Ideck
		//创建派生类型的对象,把他的地址赋给指针pDeck
pDeck = new PinochleDeckl; //new动态分配内存
...
aCard[i] = pDeck->deal_a_card;
//等价于aCard[i] = (*pDeck).deal_a_card;

接口(即基类)的指针可以再编译的时候指向一个派生类的对象,也可以在运行时根据实际情况指向不同类型的对象

class IDeck {
public:
	virtual Card deal_a_card() = 0;
};

在派生类声明的第一行中,必须在基类名称前附加public前缀,这种情况下可以使用private和protected

继承和虚函数的终极目标:1. 任何对象都可以在运行时选定,只要他的类从一个通用基类派生;2. 将调用每个虚函数的正确实现

虚函数的代价:性能和空间
需要维一个vtable指针,性能损失来源于需要更多时间发出间接函数调用,空间损失来源于vptr和表自身占用的字节)
代价小

16.2 “纯虚”和其他抽象事项

接口(或抽象类)包含纯虚函数,纯虚函数既不需要,也不期待有一个具体实现,使用**=0**记号法来标识纯虚函数。例如:

class Number{
protected:
	virtual void normalize = 0;
};
16.3 抽象类和接口

包含一个或多个纯虚函数(原型包含=0)的类称为抽象类。

抽象类的一个重要规则是不可以实例化,即不能用它声明对象
抽象类主要是为他的子类起到一个规范作用,从抽象类派生出子类,实现所有纯虚函数,最后用子类实例化对象
用子类实例化(创建)对象之前,子类必须为所有纯虚函数提供定义。
任何一个函数没有实现,当前类就还是抽象类,不可以实例化

  1. 每个子类都可采取它想要的任何方式实现所有服务(即纯虚函数)
  2. 每个服务都需要实现,否则类不能实例化
  3. 每个类都要要严格遵守类型规定,包括返回类型和每个实参的类型,这为继承层次结构制定了严格的纪律,编译器能提早发现意外
16.4 面向对象和I/O

使用各种流类来扩展输出

cout无限可扩展
要使一个类可打印,只需要operator<<函数

ostream &operator<<(ostream &os,const Fraction &fr){
	os<<fr.num<<"/"<<fr.den;
	}

使用各种I/O流不仅能输出到控制台(cout),还可输出到任何文件或字符串

Fraction fr(11;
cout << "The value is: " <<fr1;

cout不是多态的
较为具体的东西(子类)总是能传给较常规的东西(基类)

总结:

  1. 函数声明为虚,在所有子类中同样为虚,在子类中重写函数时不需要添加virtual关键字
  2. 可能被重写的任何成员函数都应声明为虚
  3. 纯虚函数在声明他的类中通常无具体实现(即没有函数定义)。用=0记号法声明虚函数:
    virtual void normalize = 0;
  4. 含有至少一个纯虚函数的类称为抽象类,不可用它实例化对象,虽然子类可以
  5. 抽象类主要用于创建接口,子类通过实现所有虚函数来提供一组服务
  6. 多态性解放了对象,避免他们相互依赖,因为对象自内建了执行服务的逻辑,正是“面向对象”一词的由来,主要面向对象而非只是,面向类
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSDN IT狂飙上传的代码均可运行,功能ok的情况下才上传的,直接替换数据即可使用,小白也能轻松上手 【资源说明】 基于MATLAB实现的有限差分法实验报告用MATLAB中的有限差分法计算槽内电位;对比解析法和数值法的异同点;选取一点,绘制收敛曲线;总的三维电位图+使用说明文档 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行本 Matlab 2020b;若运行有误,根据提示GPT修改;若不会,私信博主(问题描述要详细); 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可后台私信博主; 4.1 期刊或参考文献复现 4.2 Matlab程序定制 4.3 科研合作 功率谱估计: 故障诊断分析: 雷达通信:雷达LFM、MIMO、成像、定位、干扰、检测、信号分析、脉冲压缩 滤波估计:SOC估计 目标定位:WSN定位、滤波跟踪、目标定位 生物电信号:肌电信号EMG、脑电信号EEG、心电信号ECG 通信系统:DOA估计、编码译码、变分模态分解、管道泄漏、滤波器、数字信号处理+传输+分析+去噪、数字信号调制、误码率、信号估计、DTMF、信号检测识别融合、LEACH协议、信号检测、水声通信 5、欢迎下载,沟通交流,互相学习,共同进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值