WindyWinter windy@ream.at C++ WindyWinter windy@ream.at.

Slides:



Advertisements
Similar presentations
因数与倍数 2 、 5 的倍数的特征
Advertisements

3 的倍数的特征 的倍数有 : 。 5 的倍数有 : 。 既是 2 的倍数又是 5 的倍数有 : 。 12 , 18 , 20 , 48 , 60 , 72 , , 25 , 60 ,
第五节 函数的微分 一、微分的定义 二、微分的几何意义 三、基本初等函数的微分公式与微分运算 法则 四、微分形式不变性 五、微分在近似计算中的应用 六、小结.
阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
Oracle数据库 Oracle 子程序.
2-7、函数的微分 教学要求 教学要点.
(欢迎baj队长携夫人莅临指导,)WindyWinter感谢诸位前来捧场。 WindyWinter
第14章 c++中的代码重用.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
C++程序设计 王希 图书馆三楼办公室.
在PHP和MYSQL中实现完美的中文显示
第10讲 Java面向对象编程基础(4) 教学目标 主要内容.
第九章 字符串.
Using C++ The Weird Way Something about c++11 & OOP tricks
Signutil.
Hadoop I/O By ShiChaojie.
走进编程 程序的顺序结构(二).
辅导课程六.
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第五讲 四则运算计算器(一) 精品教程《C#程序设计与应用(第2版)清华大学出版社 谭恒松 主编
第二章 Java语言基础.
本节内容 模拟线程切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
第七章 操作符重载 胡昊 南京大学计算机系软件所.
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
Java语言程序设计 清华大学出版社 第8章 输入输出流(1).
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言程序设计 主讲教师:陆幼利.
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
C# 入门 2011级ACM班 张方魁.
$9 泛型基础.
顺序表的删除.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
本节内容 随机读取 视频提供:昆山爱达人信息技术有限公司.
第二章 Java基本语法 讲师:复凡.
保留字與識別字.
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
第4章 Excel电子表格制作软件 4.4 函数(一).
C qsort.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
第九节 赋值运算符和赋值表达式.
iSIGHT 基本培训 使用 Excel的栅栏问题
3.16 枚举算法及其程序实现 ——数组的作用.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
第4课时 绝对值.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第 8 章 标准模板库STL 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
#include <iostream.h>
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
本节内容 结构体.
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
基本知识 数据类型、变量、常量、运算符.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
插入排序的正确性证明 以及各种改进方法.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
§4.5 最大公因式的矩阵求法( Ⅱ ).
<编程达人入门课程> 本节内容 有符号数与无符号数 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
编译原理实践 6.程序设计语言PL/0.
本节内容 this指针 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
Presentation transcript:

WindyWinter windy@ream.at C++ WindyWinter windy@ream.at

C++标签

命名空间 对于一个大型的C语言软件项目,给函数和全局变量起名不是一个容易的事情,因为必须考虑有没有可能与其它程序员写的代码冲突,多数的做法是对每个模块的一组函数名加个特定前缀。比如著名的PJSIP库,它选择了在每个函数和类型的前面加上前缀“pj_”,使得标识符都比较长,而且看起来有点儿冗余。

命名空间 所以C++引入了namespace的概念,把一些标识符以命名空间树结构的方式组织起来,使代码看起来更优雅。 namespace parser { inline double get_double(char **str_ptr); inline int get_int(char **str_ptr); } namespace sight { inline AngleDeg ViewAngle(ViewWidth view_width); }

命名空间 方式一,只在必要的时候通过域运算符::引用指定命名空间内的标识符 parser::get_double(……); std::cout<<…… 方式二,把parser命名空间中的全部标识符都引入到当前编译单元中 using namespace parser; get_double(……); 方式一适用于当前编译单元引用parser内的标识符不多,而且编译单元内使用这些标识符的次数也不多的情况。 使用了using namespace之后,parser所有的标识符对于当前编译单元都是可见的。 常见的using namespace std的写法就是将std命名空间中的全部标识符引入当前编译单元,std命名空间里面全是标准库函数。

命名空间 当声明命名空间时的名称为空时,则该命名空间为匿名命名空间(unnamed namespace)。匿名的空间是C++用于定义作用域为本编译单元的函数或变量的一种新的方式。由于匿名命名空间没有命名空间的名字,所以也无法在其它的编译单元内通过extern声明该变量或函数,于是该变量自然也只在本编译单元内可见。 编译器实现的时候,实际上是为每个匿名命名空间生成了一个唯一的内部名字。

命名空间 namespace { bool ret = BehaviorExecutable::AutoRegister<BehaviorDribbleExecuter>(); } 每一个BehaviorXXX.cpp中都有一个定义在匿名命名空间里的ret变量,该变量仅仅是为了实现BehaviorXXXExecuter的注册关系,在文件之外无任何意义。

string char * -> string #include <string> string s; C++标准库提供了新的字符串实现方式string类,C的char*形式的字符串在C++中被称作“C风格字符串”。string与C风格字符串相比,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至是100%)的需要。我们可以用 = 进行赋值操作,== 进行比较,+ 做连接。我们基本可以把它看成是C++的基本数据类型。 为了在我们的程序中使用string类型,我们必须包含头文件 <string>。 这样我们就声明了一个字符串变量s。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把s初始化为一个空字符串。

string string s; //生成一个空字符串s string s(str) //拷贝构造函数 生成str的复制品 string s(str, idx) //将字符串str内“始于位置idx”的部分当作字符串的初值 string s(str, idx, len) //将字符串str内“始于idx且长度顶多len”的部分作为字符串的初值 string s(“asdf”) //将C风格字符串作为s的初值 string s(c_str, len) //将C风格字符串c_str的前len个字符作为字符串s的初值。 string s(n, c) //生成一个字符串,包含n个c字符 string s(begin, end) //以区间[begin, end)内的字符作为字符串s的初值 string还有很多构造函数。 最后一个构造函数是为了与C++标准库中其它的一些东西保持统一,我们后面再说“区间”的问题。

string C++提供的由string得到对应的C风格字符串的方法有三种: s.data(); //以字符数组的形式返回字符串内容,末尾没有\0。 s.c_str(); //返回一个以\0结尾的字符数组,也就是最标准的C风格字符串。 s.copy(c_str, n, pos); //把字符串的内容复制或写入既有的字符数组内。 data和c_str返回的均为常量,不能用这两个函数修改string的值,string的修改方法在后面。

string 访问string包含的字符——下标操作符[] string s(“asdf”); s[5] //返回\0 s.assign(str, 1, 5); //如果str是”WrightEagle”就是把”right”赋给字符串s s += str; //追加个字符串 s += ”WrightEagle”; //追加个C风格字符串 s += ’a’; //追加个字符 虽然string不像C风格字符串一样存储\0,但用[]访问最后一个字符的下一个位置时,返回\0。

string 字符串长度 取子串 insert、erase、replace compare、find、rfind s.length() 取子串 s.substr(6); //从索引6开始到结尾的子串 s.substr(1, 5); //从索引1开始5个字符 insert、erase、replace compare、find、rfind <、>、<=、>=

流输入输出 iostream  scanf/printf fstream  fscanf/fprintf cin>>XXX; cout<<XXX; fstream  fscanf/fprintf ifstream fin(“input.txt”); ofstream fout(“output.txt”); fin>>XXX; fout<<XXX; stringstream  sscanf/sprintf stringstream cmd_str; cmd_str << “(dash ” << mCommandInfo.mPower << “ ” << mCommandInfo.mAngle << “)”; iostream 的设计初衷包括克服 C stdio 的缺点,提供一个高效的可扩展的类型安全的 IO 机制。但是现在iostream过于复杂了,导致效率非常差,所以大型的工程中都避免使用。 常用的反而是stringstream,但是大家用它也只是贪图方便的将数字转换成字符串。 WrightEagleBASE很少直接使用屏幕和文件输入输出,尽量用log输出——Logger::instance().GetTextLogger(“xxx”)<<……

模板与泛型编程

模板 实践中需要各种各样的min函数 如果还需要其他类型的min怎么办? int min(int a, int b) { return a>b ? b : a; } double min(double a, double b) { return a>b ? b : a; } 如果还需要其他类型的min怎么办? char short long long-long float long-double ActiveBehavior AngleDeg 想象不止有这几个内置类型,还有很多很多很多类类型,那一个工程里面光min函数就得几十上百个;如果再加上max函数…… 这些min函数的函数体都是一模一样的,唯一不同的是参数和返回值的类型,如果能够把类型当作一个“变量”,就能大幅节省编码时间了。

模板 类型抽象——_Tp类型 Min(2, 3); Min(3.0, 4.0); Min(act_bhv1, act_bhv2); template<typename _Tp> inline const _Tp& Min(const _Tp& x, const _Tp& y) { return std::min(x, y); } Min(2, 3); Min(3.0, 4.0); Min(act_bhv1, act_bhv2); 函数模板。 _Tp叫做模板参数,代表某个类型。函数模板不是函数,需要经过一个“实例化”的过程变成函数——在首次调用的时候,编译器推断_Tp的实际类型,生成对应类型的函数。

模板 Min(1, 2.0); //推断出错 Min(player1, player2); //编译出错 如果编译器无法推断出T类型是什么(推断的时候没有隐式类型转换),那么编译出错。 如果推断出来_Tp使得代码编译不过——比如_Tp类型不能比较大小(如PlayerState),那么编译出错。

模板 template<typename _Tp, std::size_t _Nm, bool _Zero = false> class Array { _Tp _M_instance[_Nm ? _Nm : 1]; public: Array() { if (_Zero) { bzero(); } } _Tp & operator[](const std::size_t & i) { return _M_instance[i]; } }; 类也可以有模板,比如这个WrightEagleBASE中定义的“安全数组”类。 定义一个数组类型的用途,或者是好处是什么? ——检查数组越界,数组越界是常见的错误,如果在operator[]里面加入对下标的检查,可以有效避免。成为“安全数组”。 ——方便数组复制,数组不能直接复制,即使是两个类型一样的数组也不行,但是定义成数组类型,就可以利用编译器合成的拷贝构造函数复制数组。

模板 Array<int, 11> numbers; Array<PlayerState &, 11> teammates; template<typename _Tp, std::size_t _Nm, bool _Zero = false> 类模板经过实例化变成类。 实例化的方法,与函数不同,类模板实例化必须显式写出模板参数。 模板参数不同的模板实例是不同的类,彼此之间没有任何关系,不能互相访问私有成员。 模板参数不仅可以是类型名,还可以是数字、bool类型,模板参数还可以是任何可以转化为整数的东西。

标准模板库 C语言有一个小巧精干的标准库; C++在引入泛型编程的思想后,标准库得到了广泛的、革命性的变革——标准模板库。 vector、list、deque、queue、stack、priority_queue、set/map纷纷进入STL; STL中的函数不再限定参数的类型,而只做出基本要求: min、max、sort要求此种类型定义过”<“; binary_search要求传递进来的序列可以随机访问; …… vector——动态增长的数组、list——链表、deque——块状链表/双端队列,统称为容器; priority_queue——堆/优先队列,set/map——平衡二叉树,统称为容器适配器。 C标准库函数要求一个数组或序列时,常采用传递void指针+单个元素的体积的形式,STL受益于模板,不必再如此麻烦。

vector #include <vector> std::vector<PlayerState> players; players.size(); //players的长度 players.push_back(player1); //将一个元素插入到vector的最后面 insert()、clear()、erase() vector是长度可变的数组,内部机制是数组。vector可以扩大和缩小,满了之后扩容为两倍,空了之后缩小为一半。 定义一个元素为PlayerState类型的vector。一个刚刚定义的vector一个元素也没有,容量是100。 []保持了与数组的一致性,取不存在元素会出现问题,但不会报错。 通常用push_back为vector增加新元素。

list #include <list> std::list<ActiveBehavior> mActiveBehaviorList; ActiveBehavior dribble; mActiveBehaviorList.push_back(dribble); mActiveBehaviorList.sort(std::greater<ActiveBehavior>()); mActiveBehaviorList.front(); mActiveBehaviorList.empty(); list是链表,内部实现机制为双向链表。 list类型不用[]取元素。

迭代器 最简单的迭代器相当于指向容器中元素的指针; for (vector<PlayerState>::iterator i = players.begin(); i < players.end(); ++i) { i->GetPos(); (*i). GetNeckDir(); } players.end() 表示“超出末端的位置”。 i相当于players里元素的指针。 vector的迭代器可以随机访问 --i; i += 2; i -= 6; 与iterator相仿的是reverse_iterator,对应有rbegin()、rend()。 players.begin()返回一个迭代器,指向players中的第一个元素。 与指针一样,对迭代器使用解引用运算符,可以得到迭代器指向的那个元素的引用。 看下面这个循环,i初始化为players的第一个元素的位置,每次++i,表示将i后挪一个位置,players.end()表示“超出末端的位置”,于是players中每个元素的位置都在players.end()之前,当i==players.end()时,说明i已经挪到了players之外,不再指向players中某个元素的位置了。于是这个循环遍历了players中的每一个元素。 表示前移1个位置、后挪2个位置,前移6个位置,若向后挪到了players之外,则i会与playres.end()相等,向前挪到players之外,则会自动挪到第一个位置。随机访问就是指可以跳跃性的访问任意一个元素,而不需要一个一个挪。与vector相对的是,list的迭代器只能用++/--,不能随机访问。 reverse_iterator的特点是,+表示向前挪,-表示向后挪;rbegin()是最后端,rend()是“超出前端”。

迭代器 迭代器的失效——如果一个迭代器指向的元素已经被删除,那么该迭代器失效,访问该迭代器后果不可预料。 迭代器的分类: 随机访问迭代器 前向迭代器 双向迭代器 输入迭代器 输出迭代器 正向迭代器 反向迭代器 常量迭代器 流迭代器 五种迭代器——Primer 356页。 常量迭代器用于当容器是个常量,带有const属性的时候,正常的迭代器默认元素是左值,可以更改,常量迭代器指定元素是右值,就像指向常量的指针一样。

sort #include<algorithm> vector<int> a; sort(a.begin(), a.end()); vector<person> c; sort(c.rbegin(), c.rend()); int b[100]; sort(b, b+100); list<double> d; sort(d.begin(), d.end()); //X d.sort(); //O STL除了提供各种基本数据结构之外,也提供基本算法。sort是STL中提供的最常用的排序算法,在algorithm头文件中,其内部实现是冒泡排序和快速排序。 C标准库中有一个qsort函数,那个函数要求一段数组和一个比较函数。sort在这一点上与qsort很相似,它要求一对能随机访问的迭代器,一个指向序列开头,一个指向序列的“超出末端位置”, 并不要求这两个迭代器是正向的还是反向的,另外它要求被排序的序列中的元素带有<运算符,且<运算符必须被定义为严格小于——即表达式(x<x)必须返回false/0。 sort也可以用于排序数组,此时数组的头指针就是序列的开头,最后一个元素的位置+1就是“超出末端位置”。 下面,直接用sort去排序一个链表是不行的,因为sort要求随机访问迭代器,而链表的begin和end返回的迭代器不能随机访问。但链表提供了自己的sort函数,内部实现也是快速排序。 STL还提供了很多其它的小工具和小算法。

补充 C++于1983年在贝尔实验室诞生,迄今为止经历了三个发展阶段: 面向对象阶段(第一天课程),1979年~1995年。C++作为C语言的扩充,完善面向对象特性。 泛型编程阶段(第二天课程),1995年~2000年。C++的模板机制最早在1991年出现,之后HP写出了第一份标准模板库的实现,并于1994年底进入C++标准(ANSI)。到1998年C++的第一个ISO标准出现时,C++在全世界程序设计语言中的占有率达到了史无前例的76%。之后由于Java和C#等新兴语言的出现,C++不断受到冲击。该阶段到模板的集大成者——boost库出现为止。 模板元编程阶段,2000年~今。在不断尝试模板编程的过程中,人们完善C++的模板机制,直到它变成了图灵完备的(一个语言是图灵完备的,意味着该语言的计算能力与一个通用图灵机相当,这也是现代计算机语言所能拥有的最高能力)。C++的模板是所有编程语言的模板中第一个图灵完备的。于是boost库的一个分支mpl出现了。模板与泛型编程进入了模板元编程的时期,人们用模板写出了求阶乘、求素数,实现了链表,用C++做函数式编程。

Q&A http://cplusplus.com/reference/ wrighteagle-2d-training+subscribe@googlegroups.com