第十四章——C++中的代码重用

C++的一个主要目标是促进代码重用。公有继承是实现这种目标的机制之一,但并不是唯一的机制。

包含对象成员的类

valarray类简介 

valarray类是由头文件valarray支持的。这个类用于处理数值(或具有类似特性的类),它支持诸如将数组中所有元素的值相加以及在数组中找到最大值和最小值的操作。valarray被定义为一个模板类,以便能够处理不同的数据类型

模板特性意味着声明对象时,必须指定具体的数据类型。因此使用valarray类来声明一个对象时,需要在标识符valarray后面加上一对尖括号,并在其中包含所需的数据类型:

valarray<int> q_values;    //an array of int
valarray<double> weights;    //an array of double

下面是其几个构造函数的例子:

double gpa[5] = {3.1,3.5,3.8,2.9,3.3};
valarray<double> v1;        //an array of double ,size 0
valarray<int>v2(8);         //an array of 8 int elements
valarray<int>v3(10,8);      //an array of 8 int elements, each set to 10
valarray<double> v4(gpa,4); //an array of 4 elements, //initialized to the first 4 elements of gpa
 Student类的设计

学生是什么?可以将其简化为姓名和一组考试分数,则可以使用一个包含两个成员的类来表示它:一个成员用于表示姓名——string对象,另一个成员用于表示分数——valarray<double>

你可能想以公有的方式从这两个类派生出Student类,这将是多重公有继承,语法上允许,但在这里不合适,因为学生与这些类之间的关系不是is-a模型。学生不是姓名,也不是一组考试成绩。这里的关系是has-a,学生有姓名,也有一组考试分数。通常用于建立has-a关系的C++技术是包含,即创建一个包含其他类对象的类,如可以这样声明Student类

Class Student
{
private:string name;                //use a string object for namevalarray<double> scores;    //use a valarray<double> object for scores...
}
Student类示例 
#ifndef STUDENTC_H_
#define STUDENTC_H_#include<iostream>
#include<string>
#include<valarray>
class Student
{
private:typedef std::valarray<double> ArrayDb;std::string name;	//contained objectArrayDb scores;		//contained object//private method for scores outputstd::ostream& arr_out(std::ostream& os)const;
public:Student():name("Null Students"),scores(){}explicit Student(const std::string &s):name(s),scores(){}explicit Student(int n):name("Nully"), scores(n){}Student(const std::string &s,int n):name(s),scores(n){}Student(const std::string &s,const ArrayDb &a):name(s),scores(a){}Student(const char*str,const double *pd,int n):name(str),scores(pd,n){}~Student(){}double Average() const;const std::string& Name() const;double& operator[](int i);double operator[](int i)const;//friends//inputfriend std::istream& operator >> (std::istream& is, Student& stu);friend std::istream& getline(std::istream& is, Student& stu);//outputfriend std::ostream& operator << (std::ostream & os, const Student & stu);};
#endif

 为简化表示,Student类的定义中包含下述typedef:

typedef std::valarray<double> ArrayDb;

 这样类方法和友元函数可以使用ArrayDb类型。将该typedef放在类定义的私有部分意味着可以在Student类的实现中使用它,但在Student类外面不能使用

前面说过,可以用一个参数调用的构造函数将用作从参数类型到类类型的隐式转换函数,但通常这样并不好,所以用explicit关闭隐式转换。——explicit防止单参数构造函数的隐式转换

#include<iostream>
#include"studentc.h"
using std::cin;
using std::cout;
using std::endl;void set(Student& sa, int n);
const int pupils = 3;
const int quizzes = 5;
int main()
{Student ada[pupils] ={Student(quizzes),Student(quizzes),Student(quizzes)};int i;for (i = 0; i < pupils; ++i){set(ada[i], quizzes);}cout << "\nStudent List:\n";for (i = 0; i < pupils; ++i){cout << ada[i].Name() << endl;}cout << "\nResult:";for (i = 0; i < pupils; ++i){cout << endl << ada[i];cout << "average: " << ada[i].Average() << endl;}cout << "Done.\n";return 0;
}
void set(Student& sa, int n)
{cout << "Please enter the student's name: ";getline(cin, sa);cout << "Please enter " << n << " quiz scores:\n";for (int i = 0; i < n; i++){cin >> sa[i];}while (cin.get() != '\n')continue;
}

私有继承 

C++还有另一种实现has-a关系的途径——私有继承。 使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员。这意味着基类方法将不会成为派生类对象共有接口的一部分,但可以在派生类的成员函数中使用它们

 Student类示例

要进行私有继承,需要使用private关键字而不是public来定义类(实际上,private是默认类,因此省略访问限定符也将导致私有继承)。Student类应从两个类派生而来

class Student :private std::string, private std::valarray<double>
{
public:...
};

使用多个基类的继承被称为多重继承

使用私有继承时,只能在派生类的方法中使用基类的方法 

类模板

C++的类模板为生成通用的类声明提供了一种更好的方法,模板提供参数化类型,即能够将类型名作为参数传递给接收方来建立类或函数

定义模板类 

以Stack类为基础来建立模板

typedef unsigned long Item;
class Stack
{
private:enum{MAX=10};//constant specific to classItem items[MAX];//holds stack itemsint top; //index for top stack item
public:Stack();bool isempty() const;bool isfull() const;bool push(const Item& item);bool pop(Item& item);
};

采用模板时,将使用模板定义替换Stack声明,使用模板成员函数替换Stack的成员函数

模板类以下面的代码开头:

template<class Type>

关键字template告诉编译器,将要定义一个模板。尖括号中的内容相当于函数的参数列表。可以把关键字class看作是变量的类型名,该变量接受类型作为其值,把Type看作是该变量的名称。

这里使用class并不意味着Type必须是一个类;而只是表明Type是一个通用的类型说明符,在使用模板时,将使用实际的类型替换它。

所以使用模板后应该是:

bool Stack<Type>::push(const Type& item)
{...
}

 stacktp.h

#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type>
class Stack
{
private:enum { MAX = 10 };//constant specific to classType items[MAX];//holds stack itemsint top; //index for top stack item
public:Stack();bool isempty();bool isfull();bool push(const Type& item);bool pop(Type& item);
};template<class Type>
Stack<Type>::Stack()
{top = 0;
}
template<class Type>
bool Stack<Type>::isempty()
{return top == 0;
}
template<class Type>
bool Stack<Type>::isfull()
{return top == MAX;
}
template<class Type>
bool Stack<Type>::push(const Type& item)
{if (top < MAX){items[top++] = item;return true;}elsereturn false;
}
template<class Type>
bool Stack<Type>::pop(Type&item)
{if (top > 0){item = items[--top];return true;}elsereturn false;
}
#endif
 使用模板类

仅在程序包含模板并不能生成模板类,而必须实例化。为此需要声明一个类型为模板类的对象,方法是使用所需的具体类型替换泛型名。必须显式的提供所需的参数

#include<iostream>
#include<string>
#include<cctype>
#include"stacktp.h"
using std::cin;
using std::cout;
int main()
{Stack<std::string> st;char ch;std::string po;cout << "Please enter A to add purchase order,\n"<< "p to proess a PO,or Q to quit.\n";while (cin >> ch && std::toupper(ch) != 'Q'){while (cin.get() != '\n')continue;if (!std::isalpha(ch)){cout << '\a';continue;}switch (ch){case 'A':case 'a':cout << "Enter a PO number to add: ";cin >> po;if (st.isfull()){cout << "Stack already full\n";}elsest.push(po);break;case'p':case'P':if (st.isempty())cout << "Stack already empty\n";else{st.pop(po);cout << "po #" << po << " popped\n";break;}}cout << "Please enter A to add a purchase order,\n"<< "p to process a po,or Q to quit.\n";}cout << "Bye\n";return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/229771.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python基础语法之学习表达式进行符串格式化

Python基础语法之学习表达式进行符串格式化 一、代码二、效果 一、代码 print("11等于%d" % (1 1)) print(f"2/1等于{2 / 1}") print("字符串类型是%s" % type("字符串"))二、效果 坚持追求自己的梦想&#xff0c;即使道路漫长曲折&…

C语言---操作符的详解(下)

目录 1. 结构成员访问操作符 1.1 结构体 1.2结构体成员访问操作符 1.2.1 直接访问 1.2.2 间接访问 2. 操作符的属性 2.1 优先级 2.2 结合性 3. 表达式求值 3.1 整型提升&#xff08;类型小于int&#xff09; 3.2 算术转换&#xff08;类型大于int&#xff09; 1. 结构…

2023/11/28JAVAweb学习

查找哪个进程占用了该端口号 跳过某一个阶段

比特币上的有状态多重签名

无需链下通信 介绍 随着区块链和加密货币空间的发展&#xff0c;越来越需要增强安全措施来保护数字资产。 应对这一挑战的突出解决方案之一是多重签名&#xff08;多重签名&#xff09;钱包。 这些钱包在执行交易之前需要多方签名&#xff0c;从而提供额外的安全层来防止未经授…

Vue diff 算法探秘:如何实现快速渲染

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

微软Azure AI新增Phi、Jais等,40种新大模型

微软在官方宣布在Azure AI云开发平台中&#xff0c;新增了Falcon、Phi、Jais、Code Llama、CLIP、Whisper V3、Stable Diffusion等40个新模型&#xff0c;涵盖文本、图像、代码、语音等内容生成。 开发人员只需要通过API或SDK就能快速将模型集成在应用程序中&#xff0c;同时支…

docker (简介、dcoker详细安装步骤、容器常用命令)一站打包- day01

一、 为什么出现 Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build&#xff0c;Ship and Run Any App,Anywhere”&#xff0c;也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理&#xff0c;使用户的APP&#xff08;可以是一个WEB应用或数据库应…

InstructDiffusion-多种视觉任务统一框架

论文:《InstructDiffusion: A Generalist Modeling Interface for Vision Tasks》 github&#xff1a;https://github.com/cientgu/InstructDiffusion InstructPix2Pix&#xff1a;参考 文章目录 摘要引言算法视觉任务统一引导训练集重构统一框架 实验训练集关键点检测分割图像…

推荐6款交互设计软件,助你事半功倍!

交互软件可以帮助设计师从“可用性”和“用户体验”的角度优化他们的作品。如果设计师想创建一个令人满意的交互设计作品&#xff0c;一个方便的交互设计软件是必不可少的。当然&#xff0c;交互软件只是我们实现目标的一种手段。根据设计师的个人喜好和方便&#xff0c;选择易…

TS版LangChain实战:基于文档的增强检索(RAG) | 京东云技术团队

LangChain LangChain是一个以 LLM &#xff08;大语言模型&#xff09;模型为核心的开发框架&#xff0c;LangChain的主要特性&#xff1a; 可以连接多种数据源&#xff0c;比如网页链接、本地PDF文件、向量数据库等允许语言模型与其环境交互封装了Model I/O&#xff08;输入…

Wangeditor工具栏配置

包下载 pnpm add wangeditor/editor pnpm add wangeditor/editor-for-vue import wangeditor/editor/dist/css/style.css // 引入 css import { Editor, Toolbar } from wangeditor/editor-for-vue import { DomEditor } from wangeditor/editor <Toolbar style"border…

免费好用的伪原创工具推荐,都是国内的人工智能AI

在当今数字化信息爆炸的时代&#xff0c;创作者们为了在激烈的竞争中脱颖而出&#xff0c;常常需要花费大量时间来创作独特的内容。然而&#xff0c;有时候时间并不是每个人都拥有充足的资源。于是&#xff0c;一些免费智能伪原创工具成为了许多创作者的利器&#xff0c;能够在…