Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2566003
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: C/C++

2011-05-27 16:21:45

  看过了C++的书,知道友元,重载运算符,私有之类的特别有用的概念,但是没有实际操作和体会过。今天就来体验下吧。
  今天在VS下实践了一个顺序优先队列的算法和实现的编程。稍微深入的了解了下friend这个友元,还有operator这个重载运算符的妙用。感觉真的挺有用的。为了节省编写时间,就直接贴上代码(带注释的)。
  //SPQueue.h 顺序优先队列头文件
#include
using namespace std;
#define MAXSIZE 6 //最大队列长度为6

typedef struct Datatype//这个改成DataType就错了。纠结
{
int taskNo;//任务号
int priority;//优先级
}datatype;
class SqPqueue
{
public:
SqPqueue(){count = 0;}
~SqPqueue(){}
int PQueuefull();//判断队满
void InsertSQ(datatype);//插入队列
int PQueueEmpty();//判断队空
datatype DeQueue();//删除队列
//重载关系运算符<,申明为友元,friend关键字可以让一个外部方法或者/
//一个外部类访问一个类本身的私有和保护成员
friend int operator <(datatype &,datatype &);
private:
datatype data[MAXSIZE];
int count;//计数器
};
//SPQueue.cpp
#include "SPQueue.h"

int SqPqueue::PQueuefull()
{
return count==MAXSIZE;//相等,返回1
}
void SqPqueue::InsertSQ(datatype e)
{
if(PQueuefull())//如果为1,就是真
{
cerr<<"队列已满\n";
exit(1);
}
data[count] = e;
count++;
}
int SqPqueue::PQueueEmpty()
{
return count==0;
}
//外部函数,在类中已声明为友元,可以访问datatype
//重载太帅了,友元太好了
int operator < (datatype &a,datatype &b)
{
return a.priority < b.priority;//重载了<符号的定义
}
datatype SqPqueue::DeQueue()
{
if(PQueueEmpty())
{
cerr<<"队列为空\n";
exit(1);
}
datatype min = data[0];//开始选data[0]作为优先级最高的元素
int minidex = 0;//选minidex作为优先级最高的下标

//选出优先级最高的元素
for(int i = 0; i
//data[i] data[i].priority
if(data[i]
{             //因为库本身定义的<符号,不是我们所需数据类型的比较
min = data[i];
minidex = i;
}
//删除后,依次往前挪动
for(int j = minidex;j
data[j] = data[j+1];
count--;
return min;//返回优先级最高的元素
}
//main.cpp 主函数
#include
#include

#include "SPQueue.h"

void main()
{
        //具有优先级队列
        SqPqueue MyQueue;
datatype task;
int id = 1,srandNo;
cout<<"输入产生随机数种子数:"<
cin>>srandNo;
srand(srandNo);//初始化种子数
cout<<"****生成优先顺序队列****\n\n";
for(int i = 0;i
{
task.taskNo = i+1;
task.priority = rand()%10;//产生0到9之间的随机数
MyQueue.InsertSQ(task);
}
cout<<"****输出优先顺序队列****\n";
cout<<"序号  任务号   优先级\n";
while(!MyQueue.PQueueEmpty())
{
cout<
task = MyQueue.DeQueue();//找到优先级最高的任务
cout<
cout<
id++;
}
int x;cout<>x;
}

总结下:
   我认为重载运算符就是定义自己某个运算符号,用它来做自己独特数据类型的运算符操作,当然本质上还是某个具体的数据类型的比较,比如正数的比较,我们重载后,将一个结构体类型的数据拿来作为参数,然后对内部数据比较。结果就是两个整数(int)的比较转换为了两个结构体(datatype)的比较。应该挺好用的。
  对于友元来说,友元就是穿插在了两个不同模块之间。实现了一种所谓的“朋友”关系,你是我的朋友,那好,你可以访问我的私有变量。在上述例子中:int operator <(datatype &,datatype &);申明为了友元,就可以直接在外部函数实现调用datatype变量。我觉得可以不用声明为友元,在本例中。那好我们来测试下吧:我们把 friend int operator <(datatype &,datatype &);的
friend去掉----》
果然是报错了:
为什么呢??
  因为重载运算符必须放在类定义之外作为全局函数。而不能作为成员函数。好。我们把
  int operator <(datatype &,datatype &);放在类之外,就放在最后吧。
  没错了!!!如果申明为友元的话,就不用放在外面啦。这就是她的好处。
补充点:就是栈的遍历函数是这样的 void StackTraval(void (visit*)(SElemType *))
这里我查了下,说是有visit()这个函数,表示对数据结构中结点的访问,所以是传相应的参数进去,然后输出来,应该是StackTraval()函数调用给了函数作为参数。以前也用过,但是这种没怎么见过,很陌生。在主函数调用时是这样的:SqStack.StackTraval(StackPrint); void StackPrint(SElemType *);这样想来的话,就晕了。似乎用到了类型转换,还得好好研究下。
  我还要不断学习啊。希望可以慢慢学透C和C++!!请多多指教!
阅读(8383) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~