2.3模板与操作符重载
例一如有关于大小的模板函数,代码如下所示。
template<class U, class V>
bool MyGreater(U& u, V& v)
{
return u>v;
}
//这是两种类型数据泛型比较程序,在用以下代码,即基本数据类型做参数时,程序都正确
MyGreater(1,2);
MyGreater(1.5,2.5);
MyGreater('a',10);
但是当U或V有一个表示类时,编译通不过,
例如已知学生基本类代码如下所示通过构造函数可以传入学生的姓名和分数,并将其存储在类的成员变量中。
class Student
{
char name[20];
int grade;
public:
Student (char name[],int grade)//构造函数接受两个参数
{//通过 strcpy 函数将传入的 name 参数的值复制到类的私有成员变量 name 中,然后将传入的 grade
//参数的值赋给类的私有成员变量 grade
strcpy(this->name, name);
this->grade=grade;
}
}
当想获得某学生成绩是否大于 75 分时,或许希望写成如下形式
Student stud("zhang san",80)://定义学生对象
MyGreater(stud,75)://学生成绩是否大于75
当调用MyGreater 模板函数时相当于如下代码。
u是 Student 对象,是基本数据类型,两者不能直接比较,必须重载类中操作符
由于是u>v,因此必须重载 Student 类中“>”运算符
由于v是整型数,因此操作符传入参数类型是整型数;又由于仅是比较大小,返回值是 bool。
bool MyGreater(students u, int v)
{
return u>v;
}
bool operator>(const int &value)const
{
return grade>value;
}
};
最终整合代码为
#include <iostream>
#include <cstring>
using namespace std;
class Student {
char name[20];
int grade;
public:
Student(char name[], int grade) {
strcpy(this->name, name);
this->grade = grade;
}
bool operator>(const int& value) const {
return grade > value;
}
};
bool MyGreater(const Student& u, int v) {
return u > v;
}
int main() {
Student stud("zhang san", 80);
bool result = MyGreater(stud, 75);
cout << "学生成绩是否大于75: " << (result ? "是" : "否") << endl;
return 0;
}
例二以下是一个关于数组二分查找的模板函数,前提是数组按某规则已经排好序,代码如下所示。
template<class T1,class T2>
int Binaryfind(r t[], int nsize,T2 value)
//t[] 表示要查找的数组,nsize 数组大小,value:二分查找数值
//这是定义了一些变量,left 和 right 分别表示当前查找范围的左右边界,
//mid 表示当前查找范围的中间位置,
{
int left=0;
int right=nSize-1;
int mid=0;
//bFind 表示是否找到目标值的布尔变量,初始值为 false
bool bFind= false
//一个循环,不断缩小查找范围直到找到目标值或者范围为空,循环内部先计算 mid 作为当前查找范围的中间位置,
//然后通过比较 t[mid] 和 value 的大小
while(1&G(right>=left))
{
mid=(left+right)/2;
if(t[mid]==value)//a
{
bFind=true;
break;
}
if(t[mid]<value)//b
{
left=mid+l;
}
if(t[mid]>value)//c
{
right=mid-l;
}
}
//根据 bFind 的值,将 pos 设置为 mid(如果找到目标值)或者
//-1(如果没有找到目标值),然后返回 pos,表示目标值在数组中的下标。
int pos=bFind==true?mid:-1;
return pos;
}
对基本数据类型而言,直接编译执行-----------------------------------------------------------------------
首先定义了一个整型数组 a,然后通过调用 Binary find 函数分别在数组 a 中查找值 13 和 8。
将返回的结果分别存储在 pos1 和 pos2 变量中。
int main()
{
int a[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int pos1 = BinaryFind(a, 10, 13);
int pos2 = BinaryFind(a, 10, 8);
return 0;
}
但如果对类对象而言,就要考虑重载(a)(b)(c)处的操作符。
例如,学生对象数组经按成绩升序排列,现在想查询一下有无成绩是 70分的学生
Student s[]=···;//初始化完毕
Binary_find(s,10,70);//查询 10个学生集合 s[]中有无成绩 70分的学生这样可以得出,
模板参数 T1对应 Student,模板参数T2对应int
因此Student类应重载 operate==_operate>、operate<操作符
class Student
{
char name[20];//姓名
int grade;//成绩
public;
Student(char name[],int grade){
strcpy(this->name,name);
this->grade=grade;
}
bool operator> (const int value)const{
return grade>value;
}
bool operate< (const int svalue)const{
return grade<value;
}
bool operate==(const int &value)const{
return grade==value;
}};
由于 STL 中有大量的模板函数,因此很多时候要重载与之对应的操作符。
模板函数相当于已编制好的应用框架,操作符重载相当于调用的接口。
2.4 习题
1、 class Student {
char name[20];
int grade;
public:
Student ( char name[ ], int grade ) {
strcpy( this->name, name );
this->grade = grade;
}
( )
};
以下选项中能实现正确比较Student对象成绩大小的函数是()。
A.bool operator>( int&value ) const { return grade > value; }
B.bool operator>( const int &value ) const { return grade > value; }
C.bool operator>( int&value ) { return grade > value; }
D.bool operator>( const int &value ) { return grade > value; }
在选项 B 中,参数 value 被声明为 const int&,表示它是一个常量引用,避免了不必要的拷贝。而成员函数本身也被声明为 const,表示它不会修改对象的状态。
2、从公司职员中查找所有年龄等于28的职员,并显示输出,要求使用 find代码和操作符重载,补全下面部分代码(15分)
#include <iostream>#include <vector>#include <string>#include <algorithm>
using namespace std;
class Employee {
private:
string m_name;
int m_age;
public:
friend ostream& operator<<(ostream&, const Employee&);
Employee (string name, int age): m_name(name), m_age(age) {}
操作符重载 5分
bool operater==(int n) { return m_age==n;}
};
ostream& operator<<(ostream& os, const Student& s) {
os << s.m_name << “\t” << s.m_age;
Return os;
}
int main() {
vector< Employee > v;
Employee e1("li", 30); Employee e2("zhao",28); Employee e3("wang", 28);
v.push_back(e1); v.push_back(e2);v.push_back(e3);
查询并使用<<输出,每行一条记录 10分
auto it=find(v.begin(),v.end(),28);
while (it!=v.end())
{ cout<<*it<<endl;
it=find(it,v.end(),28);}
return 0;
}
3.现有试题从vector<Student>中查找成绩等于60的学生,并显示输出。补充所需的find算法,student类的操作符重载,标准输出的重载,补全下面①②③部分代码?(12分)
【bool operator>(const int& value) const {return grade > value;}};bool MyGreater(const Student& u, int v) {return u > v;}】
#include <iostream>#include <vector>#include <string>#include <algorithm>
using namespace std;
class Student{
private:
string m_name;
int m_grade;
public:
Student(string name,int grade):m_name(name),m_grade(grade){}
int getGrade() const {return m_grade;}
string getName() const {return m_name;}
//操作符重载
bool operator==(const int& value) const {
return m_grade == value;
}
};
②//标准输出重载
ostream& operator<<(ostream& os, const Student& student) {
os << "Name: " << student.getName() << ", Grade: " << student.getGrade();
return os;
}
int main(){
vector<Student> students;
students.push_back(Student("Alice", 80));
students.push_back(Student("Bob", 60));
students.push_back(Student("Charlie", 70));
int targetGrade = 60;
// 使用 auto 关键字推导迭代器类型
③ auto it = find(students.begin(), students.end(), targetGrade);
if (it != students.end()) {
cout << "Student found: " << *it << endl;
} else {
cout << "Student not found." << endl;
}}
4.操作符重载
bool operator>(const int &value)const {return grade>value;}
重载全局函数operator<<
template<class T>
ostream& operator< <(ostream& os, Unit<T>& s)
{os<<S.value;return os;}
输入输出流的重载
istream& operator>>(istream& is, Student& s)
{ is>>s.strName>>s.strSex>>s.nAge;
return is;}
ostream& operator<< (ostream& os, Student& s)
{ os<<s.strName<<” \t"<<s. strSex<<"\t"<<s nAge<<"\n";
return os;}
5.编写学生类,包含成员成员函数和成员对象。重载
#include<algorithm>
#include<list>
#include<string>
#include<iostream>
using namespace std;
class Student{
private:
string studNo;string studName;int Chinese;int Math;
public:
Student(string studNo, string studName, int Chinese, int Math):studNo(studNo),
studName(studName),Chinese(Chinese),Math(Math){ }
bool operator<(Student& s) const{
return ((this->Chinese+this->Math) < (s.Chinese+s.Math));}
friend ostream& operator<<(ostream& os, const Student& s);};
ostream& operator<<(ostream& os, const Student& s){
os << s.studNo << '\t' << s.studName << '\t' << s.Chinese + s.Math << endl;
return os;}
class StudManage{
list<Student> l;
public:
void Add(Student s){l.push_back(s);}
void Display(){
l.sort();
list<Student>::reverse_iterator rit = l.rbegin();
while (rit != l.rend()){
cout << *rit++ << endl;} }
};
int main(){
Student s1("001", "s1", 80, 90);Student s2("002", "s2", 45, 86);Student s3("003", "s3", 76, 85);
StudManage sm;
sm.Add(s1);
sm.Add(s2);
sm.Add(s3);
sm.Display();
if(getchar() != '\n')return 0;}