#include <iostream>
#include "..\testa\lS_utinity.h"#include <list>#include <vector>#include "stdio.h"#include <map>//代理类,可以默认,就可以用对象数组,成员为指针,可以为0.有copy3件套.代理行为,检测0,
//什么时候需要写继承.感觉应该必须满足一个条件.就是需要多态.如果不需要多态.就算是is a,关系.也没有必要非整出一个基类.//只要继承,就会使用指针来表示多态.只要有指针,就必须用代理类.//所以只要继承就必须代理.using namespace std;
class vehicle{ public: virtual double weight()=0; virtual void start()=0;};class bike:public vehicle
{ public: double weight(); void start();};class bus:public vehicle
{ public: double weight(); void start();};class car:public vehicle
{ public: double weight(); void start();};double bike::weight()
{ return 200;}void bike::start(){}
double bus::weight()
{ return 2000;}void bus::start(){}
double car::weight(){ return 400;}void car::start(){}
class pm
{ public: pm(vehicle*); vehicle* getP(); ~pm();private: pm(); pm(const pm&); pm operator=(const pm&); vehicle * pveh;};pm::pm(vehicle* _p):pveh(_p){}
pm::~pm(){delete pveh;}vehicle* pm::getP(){return pveh;} //一,对于单资源(狭义上就是内存,再狭义就是堆内存)的使用和管理.//1,资源的建立和托管必须是一个步骤.2)托管对象必须保证和资源同生死.//对于栈内存,.bike mybike1; 对于堆内存.bike * mybike2=new bike();//第一种,很可靠.//第二种,需要显示维护内存,和保护指针变量.所以引出一条款(effect c++),用对象管理资源.//而资源管理对象和资源同生死.就必须保证资源建立和对象建立是原子操作.也是另一条款.//并且资管,由于资源入对象是原操,那么资管必须负责资源的delete.//1)资管必须负责资源的delete.//2)负责delete,也就必须考虑资源copy三函数,构造,赋值,析构.//3)资管可以没有默认的构造函数,//4)可以直接用方法提供只读的资源地址,供外部使用//对于第2条.如果是资源地址copy.资管转化为智能指针类.//如果是资源copy.提供正确的构造,赋值,析构.//如果是禁止资源copy,构造,赋值,析构.设置为private.//如果是资源转移.提供正确的构造,赋值,析构. //所以最终对于单资源的资源的使用.在c++中有2种比较可靠的方法.//1)栈内存, bike mybike1;//2)堆内存,pm mypm(new bike());//对于多资源的统一使用和管理.
//基本是对于含有继承关系的对象而言.没有继承关系,谈不上统一管理.//那么必须是管理指针.参考上面分析.必须建立对象.//那么必须要求资源有默认的构造函数.
void showWeight(vehicle * _p)
{ cout<<_p->weight()<<endl;}int main()
{ //地址copy,使用智能指针类. bike mybike1; cout<<"**auto p***"<<endl; showWeight(&mybike1);//地址copy,使用智能指针类.
cout<<"**copy p***"<<endl; pm_copyP<bike> mypm(new bike()); pm_copyP<bike> mypm2=mypm; pm_copyP<bike> mypm3(new bike()); mypm3=mypm;showWeight(mypm.getP());
showWeight(mypm2.getP()); showWeight(mypm3.getP());//禁止copy值或地址.使用禁止类.
cout<<"**forbiden***"<<endl; pm_forbidP<bike> mypm4(new bike()); showWeight(mypm4.getP()); //pm_forbidP<bike> mypm5=mypm4;//禁止复制,赋值.//value copy,使用value-copy类.
cout<<"**copy value***"<<endl; pm_copyValue<bike> mypm5(new bike()); pm_copyValue<bike> mypm6=mypm5; pm_copyValue<bike> mypm7(new bike()); mypm7=mypm5;showWeight(mypm5.getP());
showWeight(mypm6.getP()); showWeight(mypm7.getP());//转移资源所有权, 使用transforP类. 这个和其他有不同.使用指针必须先判断,指针是否已经转移,为0了.
cout<<"**transforP***"<<endl; pm_transforP<bike> mypm8(new bike()); pm_transforP<bike> mypm9=mypm8; pm_transforP<bike> mypm10(new bike()); mypm10=mypm8;if(mypm8.getP()!=0)
{ showWeight(mypm8.getP()); } if(mypm9.getP()!=0) { showWeight(mypm9.getP()); } if(mypm10.getP()!=0) { showWeight(mypm10.getP()); }
// vehicle* allCar[100]={0};
//// bike mybike1;// bus mybus1;// car mycar1;//// allCar[0]=&mybike1;//这里是函数内,如果是外部参数,那么会有悬指针问题.所以条款,对象管理资源很必要.// allCar[1]=&mybus1;// allCar[2]=new car;//这里必须管理内存.////// for(int i=0;i!=100;++i)// { // if(allCar[i]!=0)// { // cout<< allCar[i]->weight()<<endl;// }// }
return 0;
}
#ifndef LS_UTINITY_H_INCLUDED#define LS_UTINITY_H_INCLUDED#include#include #include
using namespace std;//智能指针template class auto_MyP{public: auto_MyP (); auto_MyP (T const* _p); auto_MyP (const auto_MyP&); auto_MyP & operator=(const auto_MyP&); T* getP()const; ~auto_MyP (); void del();private: int * count_ref; const T* autop;};template auto_MyP ::auto_MyP(){ autop=0x0; count_ref=new int(1);}template auto_MyP ::auto_MyP(T const* _p){ cout<<"p con:"<<_p< auto_MyP ::auto_MyP(const auto_MyP& _lht){ autop=_lht.autop; ++(*_lht.count_ref); count_ref=_lht.count_ref;}template auto_MyP & auto_MyP ::operator=(const auto_MyP& _lht){ if(this!=&_lht) { del(); this->autop=_lht.autop; *_lht.count_ref=*_lht.count_ref+1; this->count_ref=_lht.count_ref; } return *this;}template auto_MyP ::~auto_MyP(){ del();}template void auto_MyP :: del(){ cout<<"false del:"<<*(this->count_ref)<<". add"< < count_ref)=*(this->count_ref)-1;//前后自增加,就是此语句取值是取+1变量,还是把+1给临时变量,取值去取未+1的符号变量. if(*(this->count_ref)==0) { cout<<"del:"< < T* auto_MyP ::getP()const{ return const_cast (autop);}//Merge sorttemplate list mergeSort(const list & source);template list mergeSort(const list & source){ list ret; if(source.size()==1) { ret=source; } else if(source.size()==2) { typename list ::const_iterator firstit=source.begin(); T firstvalue=*firstit; typename list ::const_iterator secondit=++firstit; T secondvalue=*secondit; if(firstvalue<=secondvalue) { ret=source; } else { ret.push_back(secondvalue); ret.push_back(firstvalue); } } else { unsigned int count_list=source.size(); unsigned int modN= count_list%2; unsigned int subret=count_list/2; typename list ::const_iterator it=source.begin(); list leftS; list rightS; for(int i=0;i!=subret+modN;++i) { leftS.push_back(*it); ++it; } for(int i=0;i!=subret;++i) { rightS.push_back(*it); ++it; } leftS=mergeSort(leftS);//lefts 传递const 引用,效率和安全,不会改动.返回对象.lefts被copy赋值函数处理. rightS=mergeSort(rightS); typename list ::const_iterator lefttop=leftS.begin(); typename list ::const_iterator righttop=rightS.begin(); while(lefttop!=leftS.end() || righttop!=rightS.end()) { // check each top if(*lefttop<=*righttop) { ret.push_back(*lefttop); ++lefttop; } else { ret.push_back(*righttop); ++righttop; } } if(lefttop!=leftS.end()) { //push no process data for(lefttop;lefttop!=leftS.end();++lefttop) { ret.push_back(*lefttop); } } else if(righttop!=rightS.end()) { for(righttop;righttop!=rightS.end();++righttop) { ret.push_back(*righttop); } } return ret; } return ret;}//template void quickSort(vector & source, int startIndex, int endIndex){ if(startIndex int centerFind(const vector & source,const T& finder){ int ret=-2; int startIndex=0; int endIndex=source.size()-1; int CenterIndex=startIndex+(endIndex-startIndex)/2; while(ret==-2) { if(CenterIndex==startIndex&&startIndex==endIndex)//1个数 { if(source[CenterIndex]==finder) { ret=CenterIndex; } else { ret=-1; } } else { if(source[CenterIndex]==finder) { ret=CenterIndex; } else if(source[CenterIndex]>finder) { endIndex=CenterIndex-1; CenterIndex=startIndex+(endIndex-startIndex)/2; if(startIndex>endIndex) { ret=-2; } } else { startIndex=CenterIndex+1; CenterIndex=startIndex+(endIndex-startIndex)/2; if(startIndex>endIndex) { ret=-2; } } } } return ret;}template class pm_copyP{public: pm_copyP(T* _p); pm_copyP(const pm_copyP&); pm_copyP& operator=(const pm_copyP&); ~pm_copyP(); T* getP();private: pm_copyP(); T* myp; int * count_ref; del();};template pm_copyP ::pm_copyP(T* _p):myp(_p),count_ref(new int(1)){}template pm_copyP ::pm_copyP(const pm_copyP& _pm){ myp=_pm.myp; count_ref=_pm.count_ref; ++(*count_ref);}template pm_copyP & pm_copyP ::operator=(const pm_copyP& _pm){ if(&_pm!=this) { del(); myp=_pm.myp; count_ref=_pm.count_ref; ++(*count_ref); } return *this;}template pm_copyP ::~pm_copyP(){ del();}template pm_copyP ::del(){ --(*count_ref); if(*count_ref==0) { delete myp; delete count_ref; }}template T* pm_copyP ::getP(){ return myp;}template class pm_forbidP{public: pm_forbidP(T* _p); ~pm_forbidP(); T* getP();private: T* myp; pm_forbidP(); pm_forbidP(const pm_forbidP&); pm_forbidP& operator=(const pm_forbidP&);};template pm_forbidP ::pm_forbidP(T* _p):myp(_p){}template T* pm_forbidP ::getP(){ return myp;}template pm_forbidP ::~pm_forbidP(){ delete myp;}template class pm_copyValue{public: pm_copyValue(T* _p); pm_copyValue(const pm_copyValue&); pm_copyValue& operator=(const pm_copyValue&); ~pm_copyValue(); T* getP();private: T* myp; void del(); pm_copyValue();};template pm_copyValue ::pm_copyValue(T* _p):myp(_p){}template pm_copyValue ::pm_copyValue(const pm_copyValue& _pm):myp(new T(*_pm.myp)){}template pm_copyValue & pm_copyValue ::operator=(const pm_copyValue& _pm){ if(&_pm!=this) { del(); myp=new T(*_pm.myp); } return *this;}template pm_copyValue ::~pm_copyValue(){ del();}template void pm_copyValue ::del(){ delete myp;}template T* pm_copyValue ::getP(){ return myp;}template class pm_transforP{public: pm_transforP(T* _p); pm_transforP(pm_transforP&); pm_transforP& operator=(pm_transforP&); ~pm_transforP(); T* getP();private: T* myp; void del(); pm_transforP();};template pm_transforP ::pm_transforP(T* _p):myp(_p){}template pm_transforP ::pm_transforP(pm_transforP& _pm):myp(_pm.myp){ _pm.myp=0;//const 怎么可以修改.}template pm_transforP & pm_transforP ::operator=(pm_transforP& _pm){ if(this!=&_pm) { del(); myp=_pm.myp; _pm.myp=0;//const 怎么可以修改. } return *this;}template pm_transforP ::~pm_transforP(){ del();}template void pm_transforP ::del(){ if(myp!=0) { delete myp; }}template T* pm_transforP ::getP(){ return myp;}#endif // LS_UTINITY_H_INCLUDED
关于异常:
#include#include using namespace std;//c++,实在经验不足.感觉只能是,使用某些函数,又不想每次都检测是否返回正确.那么抛出错误.程序结束.//感觉还不如返回错误代码呢.int dev(int a,int b);int main(){ int result=0; try { result=dev(3,1); } catch(exception &e) { //提示错误,保存关键数据,程序退出 cout< <
关于类的数据成员和参数问题。以及const。
1)类的data member.
如果是内置类型或类的值类型,语义就是局部数据,const语义就是,在类内,一个局部常量.如果是内置类型或类的指针或引用类型,语义就是局部的指针,指向外部数据,const语义就是,在类内,不可通过此指针修改外部数据.如果是内置类型或类的智能指针类型.语义就是局部数据,但里面有指针指向外部数据.const语义就是,在类内,不可通过此局部数据中的指针修改外部数据. (可以完全代替第二种,只是size为8,而第2中size是4(32system)).如果是内置类型或类的智能指针的指针或引用类型.语义就是很大概率是你想的的太复杂了.请退化为第3种.智能指针就是为了自动释放内存. 再保存它的指针,又把问题解决方案变成了问题本身.餐巾纸的作用就是为了吃饭时,让衣服更干净.为了方便拿东西.又套一个外套,还不如拿掉餐巾纸. 但是构造函数的参数应该使用 智能指针的reference,这个时候智能指针当成一般类处理.智能指针本质就是一个类了.总结:
值还是智能指针(指针),还是引用.从数据库讲,一个字段不是另一个表的key。那么就是值。否则就是引用。如果表不存在这个字读。那么就是用方法返回数据(查询其他表)
const还是非const?
可修改用非const.否则用const.对于智能指针,指针不可修改用 const shared_ptr<T>,指针所指的数据不可修改用shared_ptr<const T>.从数据库讲。如果一个字段设置了触发器,字段是只读了。那么类中。一定要是const。
2)类的constructor的参数.如果参数是内置类型或类的值类型,语义就是会创建一个原数据的副本,压入函数体.const语义就是,此参数的数据不可修改.但可以赋值给const或非const.如果参数是内置类型或类的指针或引用类型,语义就是引用原数据,压入原数据的指针到函数体.const语义就是此地址的指向不可修改.如果参数是内置类型或类的智能指针类型.语义就是会创建一个原数据(包含一个指针)的副本,压入函数体.const语义就是,此参数的数据不可修改.也就是里面的地址的指向不可修改.
时钟周期
时钟周期也称为振荡周期,定义为时钟脉冲的倒数(时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时钟周期就是1/12us),是计算机中的最基本的、最小的时间单位。 在一个时钟周期内,CPU仅完成一个最基本的动作。时钟脉冲是计算机的基本工作脉冲,控制着计算机的工作节奏。时钟频率越高,工作速度就越快。 8051单片机把一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示)。
机器周期
计算机中,常把一条指令的执行过程划分为若干个阶段,每一个阶段完成一项工作。每一项工作称为一个基本操作,完成一个基本操作所需要的时间称为机器周期。8051系列单片机的一个机器周期由6个S周期(状态周期)组成。 一个S周期=2个节拍(P),所以8051单片机的一个机器周期=6个状态周期=12个时钟周期。 例如外接24M晶振的单片机,他的一个机器周期=12/24M 秒;
指令周期
执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需的机器周期也不同。
int main(void)
{ char buf[10]; int n = read(STDIN_FILENO, buf, 10); write(STDOUT_FILENO, buf, n); return 0; }
输入字符,回车后。。。。。
少于等于10个ok。大于10个。后续的字符,和回车键都还在标准输出中,会认为用户敲入了命令。
关于开发整体流程。
//对于开发的流程,个人倾向,先建模,后建表.再实际建立class.
//因为先建立表,可以更快理清类之前细节.因为建类的时候需要考虑实际数据的存放问题.//建立类的时候,发现问题.也可以修改表.//而建立好类,不满足表,改类就麻烦.//再次.表的话更直观,可以先不考虑细节.从整体掌握模型的数据流是否正确.//甚至,类中犯的错误的设计,在表中就不太会出现.如员工,和职务.表明显会有好几个.一个员工表,几个不同职务表.//而类,可能会设计为一个类.建模错误,会导致表设计不符合表设计范式.//但是设计表的时候也可以考虑一下类.是否需要多一个表,来表现包含关系.或继承关系.
再一次卡在设计流程上了。
继续卡在无数据库设计上。
有数据库设计,数据存放问题不用考虑。而无数据库,放在那里,用 vector 对象还是指针,总是感觉设计不好。用vector或智能指针。
应该还是基于分析后。关系型数据设计开路(好理解,也很熟悉),数据存放问题的话。去掉表的外键,放入外键所在的表。用vector直接存放对象。,vector自己离开作用域会自动析构。析构会调用成员的析构函数并释放堆空间。完美啊。
可以先省去内部中其他类的集合。从上往下设计下来就好,下级设计好了。再返回上级,使用下级的初始化函数,来修改上级的初始化函数或其它初始化的地方。
这样设计了数据的流向后,再从面向对象的思维,设计行为。来给数据流向取个名字。
对象间的数据存放问题。
1)如果原本数据成员都不多。那么偏向一方(其中有确定数据属于的那方)。
2)用map存储数据。类方法提供对map的真删改,查, 类本身或管理类提供逻辑,调用增删改,特别注意逻辑中含删除的操作。
单个数据直接放栈,如果太大用智能指针。如果是不确定的多个数据或者多个大数据。用vector就好了。甚至单个大数据也可以用vector,vector自己离开作用域会自动析构。析构会调用成员的析构函数并释放堆空间。完美啊。
定义参数值用全局const。但如果是状态返回值或者作为参数可以用enum.这样就可以限定返回的数据范围。但是枚举不能设定数据类型。比如int_8,所以在网络编程需要固定长度的时候又很尴尬。
模型设计的一点想法,
看了下网狐。有个设计,类之间的包含关系 ,不放指针,或智能指针。
直接放一个key.
所以设计的时候,
1.可以先设计一个对象,包含属性和方法。
2.再设计一个管理类,包含一个当前key 的最大小(根据情况,是先进先出,还是先进后出)值。 用int 记录。
一般可以用int ,取int最大值为默认值,表示下次插入的key。插入的时候用这个做key.并·--, 删除的时候,看看要删除的是不是等于 key-1.如果是,++。 所以用map的key,来当前数据库的外键。
好处是避免了指针的坏处。指针可能有移动操作,也比较危险。而用 key,自然的多。终于解决了这个疑问。
封装的一个含义就是类的某个或几个数据是状态数据。他的改变只由行为(方法)来改变。并提供只读的查看。
服务端和客户端同步开发。
客户端的初始化行为放入main中(之后可以由网络模块发送消息,获得消息,并回调这些方法)。
客户端的动作逻辑封装成方法(之后由网络模块发送消息,获得消息,并回调这些方法)
服务端是一个完备的系统,应该是一个可以自检,自运行的系统。客户端只是通过发送消息,改变服务端的自运行的过程中的状态值。
c#
RoomInfo selectroom = rooms.Where(s => s.room_id == (SByte)this.comboBox1.SelectedValue).Single();
where 相当于里面一个bool函数。where里面已经回调了()里面的函数。并根据bool值来决定是否加入结果集合。
c++ get .set 生成器。
Listinputcode = new List (); List outputcode = new List (); string className = this.textBox3.Text.Trim(); inputcode = this.textBox1.Text.Split(new string[] { "\r\n"}, StringSplitOptions.RemoveEmptyEntries).ToList(); for(int i=0;i
目的:有时候有些情况比较复杂,写完了代码。也没法确定是否完全正确。画图感觉比较复杂,只能靠测试。这个时候使用状态机分析法。就能比较好。
步骤:先写出初始行为,和输入行为,以及输入行为对应的猜想的动作,通过猜想的动作,对状态的更改,判断状态是否合理,来验证行为是否正确。每次集合中所有状态和行为一一匹配。有新状态。就保存。 之后每次用新状态和所有行为一一匹配。直到没有新状态为止。初始状态: r_ok,s_ok,e_in;
输入行为和对应猜想动作()
1)recv_again. r_ok2)recv_close. r_close,cancel event3)recv_error. del4)send_ok. s_ok ,1)close:yes,block:yes=>s_ok 2)close:yes,block:no => s_ok 3) colse:no,block:yes=>s_ok. e_in. 4)close:no,block:no=>s_ok5)send_block. s_block,mod e_out6)send_err. del初始状态: 下和所有输入行为产生的新状态1:r_ok,s_ok,e_in;
1-1)=>
1-2)=>r_close,s_ok1-3)=>del1-4)=>r_ok,s_ok,e_in1-5)=>r_ok,s_block,e_out1-6)=>del状态应该正确。所以猜想行为暂时正确。在用得到的新状态,和所有行为一一匹配1:r_close,s_ok2:r_ok,s_block,e_out1-1)=>不可能会存在的行为
1-2)=>不可能会存在的行为1-3)=>不可能会存在的行为1-4)=>1-5)=>r_close,s_block, e_out1-6)=>del2-1)=>不可能会存在的行为
2-2)=>不可能会存在的行为2-3)=>不可能会存在的行为2-4)=>2-5)=>2-6)=>del又得到1种新状态。所有状态是2×2×2.现在只有4种。
在用得到的新状态,和所有行为一一匹配1:r_close,s_block, e_out1-1)=>不可能会存在的行为1-2)=>不可能会存在的行为1-3)=>不可能会存在的行为1-4)=>1-5)=>1-6)=>del 无任何新状态。估算下是否正确估算下,还有剩下4种是什么情况。1:r_ok,s_ok,e_in;2:r_ok,s_block,e_out3:r_close,s_ok4:r_close,s_block, e_out哦。因为s_ 和e_只能组合成2种。所以就是4种。所以我们得到了全部状态。再验证一下猜想行为就好了。虽然很烦琐,但是可以验证遗漏的情况。
测试epoll的时候,客户端可以线程10个内。但是开多点socket ,100左右。这样简陋的环境。也可以测试高流量,模拟高并发。注意看服务的发送和接受是否相同大小,如果是echo测试。
还要看客户端的接受。是否有重传现象。如果客户端接收的明显比服务端发送的多。
如何测试epoll的代码效率。
可以简单点。客户端开1000个socket.200毫毛休息一次。说明1秒有5000条信息处理。每条信息64B。发送速度就是300/kB.
服务端,每条信息的处理休息1毫秒。说明1秒处理1000条。但是测试还是不准。所以可以调整下。用netstat 命令查看。使得接受数据越来越多为好。说明程序处理慢。
这样就可以开始优化了。单线程可以优化批量发送,批量处理。
多线程就可以开始队列,新线程处理。多线程的一般特征是网路是没有问题的。接受快,发送快。因为单独线程再处理io。但是如果程序差,那么内存会原来越小。因为网络的数据全部拉到内存中去了。但是又处理不过来。