走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。

Slides:



Advertisements
Similar presentations
移动应用软件开发技术 第二讲:C++编程基础
Advertisements

程序设计实习 3月份练习解答
Memory Pool ACM Yanqing Peng.
第九讲 类与对象 (I)面向对象基础.
第4章 数组 数组是由一定数目的同类元素顺序排列而成的结构类型数据 一个数组在内存占有一片连续的存储区域 数组名是存储空间的首地址
類別與物件 Class & Object.
第15章 繼承與多重繼承 15-1 繼承的基礎 15-2 覆寫與隱藏父類別的成員 15-3 子類別的建構與解構子 15-4 多重繼承
第八章 类和对象.
C++程序设计 王希 图书馆三楼办公室.
C++语言程序设计教程 第7章 类与对象 第7章 类与对象.
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
資料大樓 --談指標與陣列 綠園.
内容提要 对象的生命周期 构造函数 析构函数 拷贝构造函数. 常宝宝 北京大学计算机科学与技术系
Chap 18 類別與物件 夫有土者,有大物也。有大物者,不可以物。 物而不物,故能物物。 明乎物物者之非物也,豈獨治天下百姓而已哉!
4.1 概述 4.2 类与对象的实现 4.3 对象的初始化和析构 4.4 类的包含 4.5 类模板
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
教材 《C++程序设计》.谭浩强. 清华大学出版社 王雪晶
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
西安交通大学 计算机教学实验中心 大学C++程序设计教程 西安交通大学 计算机教学实验中心
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
程序设计期末复习 黎金宁
第三章 C++中的C 面向对象程序设计(C++).
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
C++语言程序设计教程 第7章 类与对象 第7章 类与对象.
第一章 C++编程简介 丘志杰 电子科技大学 计算机学院 软件学院.
C++程序设计 string(字符串类) vector(容器类).
类类型 C++支持的内置类型和操作,如 int i=10; i=i%6; i=i+4;
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
第二章 基本数据类型及运算 C数据类型概述 基本数据类型 运算符和表达式 混合运算与类型转换 数据的输入输出 顺序程序设计举例.
Chapter 2 & Chapter 3.
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
潘爱民 C++ Overview 潘爱民
C#程序设计基础 $3 成员、变量和常量.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
保留字與識別字.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
物件導向程式設計 CH2.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
第三章 数据抽象.
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
C++程式設計入門 變數與運算子 作者:黃建庭.
C++大学基础教程 第10章 运算符重载 北京科技大学 2019/5/7 北京科技大学.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第1章 C++面向对象程序设计要点 1.1 函数和函数参数 1.2 输入输出   1.3 类 1.4 抽象类型和模板.
第 9 章 建構函式與解構函式.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
#include <iostream.h>
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
JAVA 程式設計與資料結構 第三章 物件的設計.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
本节内容 在堆中创建对象 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
變數與資料型態  綠園.
資料!你家住哪裏? --談指標 綠園.
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

走向C++之路 WindyWinter windy@ream.at WindyWinter感谢诸位前来捧场。 #include <stdio.h> main(t ,_,a) char*a;{return t<1?main(*a,a[-t],"=a-1kj3gnm:q\ ebh_cf*<r.d>i^+?,()[?qzyrjuvcdefg\ h,!kbpolwxs'.t main(")&&a[-t]&&main (t-1,_,a):t/2?_==*a?putchar(32[a]) :_%115<36||main(t,_,a+1):main( 0,t,"+b:s?#mw{ty}t(x1{|~?\ y<#q?(*#{k)}rsh?vts){\ ?w*#yk<y,}w}z!w)v\ ~>u:!zym^t|x|\ |xtutu!uz\ |#}t") ;}

课程适用性 迫于时间所限,本课程只能面向C语言程序设计基础较好的同学, 并且希望经过短期训练,让你能读懂、写出合格的C++程序, 至少不再认为今后将面对的RoboCup 2D球队底层是天书, 以及改善面对超过一个文件的工程即手足无措的状况。 注意:本课程不会建立面向对象和泛型编程的思维模式,因此不能替代《面向对象程序设计》。 建议比较勤快的同学脱离本课程,用《C++ Primer》自学C++语言。 合格的C++入门和参考书籍有《C++ Primer》《The C++ Programming Language》和《Thinking in C++》 C++是C的超集。C99标准有550页,C++03标准有786页。即使你完全记得550页的C99标准说了什么,也还有200多页需要钻研,何况你我都清楚,能记得250页的就已经非常了得了。所以,培训的目标仅仅限定于编写联赛用的球队可能会使用到的C++的特性,而其他的地方,则能省就省。 《C++ Primer》适合入门,《Thinking in C++》适合对C非常熟悉的同学,《The C++ Programming Language》则适合已经对另外一门语言(面向对象的)非常熟悉的同学。

为你的程序贴上C++的标签 从这里开始 C++是C的超集,也就是说,大部分C程序都可以不经改变的直接被C++编译器编译通过(除非C程序中用到了C++的保留标识符)。但贴上C++的标签看起来更好一些。

一个著名的C程序 #include <stdio.h> void main() { int i; for (i=0; i<10; ++i) printf(“Hello World!\n”); } 为了给出一个直观的印象,我们先看一看C++程序跟C程序的相貌差别。 #include <stdio.h> main(t ,_,a) char*a;{return t<1?main(*a,a[-t],"=a-1kj3gnm:q\ ebh_cf*<r.d>i^+?,()[?qzyrjuvcdefg\ h,!kbpolwxs'.t main(")&&a[-t]&&main (t-1,_,a):t/2?_==*a?putchar(32[a]) :_%115<36||main(t,_,a+1):main( 0,t,"+b:s?#mw{ty}t(x1{|~?\ y<#q?(*#{k)}rsh?vts){\ ?w*#yk<y,}w}z!w)v\ ~>u:!zym^t|x|\ |xtutu!uz\ |#}t") ;}

贴上C++的标签 #include <iostream> using namespace std; int main() { for (int i(0); i<10; ++i) cout<<“Hello World!”<<endl; } return 0; 可以看出,C++特有的标签还是不少的,首先是标准库头文件没有了.h后缀,后面又有一个using namespace std的写法,main函数被强制规定为int类型,for循环首部可以新定义变量,初始化也有了新的写法,至于printf,则干脆变成了cout。这些改变我们将在后面一一讲明。 namespace叫做“命名空间”,C++的设计者认为,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,标识符重名的概率非常大,于是设计了 “命名空间” ,每个命名空间中的函数、变量等等互不干扰,重名也没关系。

C++与C的相貌差别 C的写法 C++写法 Glance #include<stdlib.h> _Bool scanf(“%d%d”,&a,&b); printf(“%d%d”,c,d); int *p = malloc(sizeof(int)); free(p); char str[]=“WindyWinter is talented.”; int a[10]; char b[20]; double c[30]; #include<cstdlib> bool int a,b; cin>>a>>b; cout<<c<<d; int *p = new int; delete p; string str(“WindyWinter is talented.”); vector<int> a; vector<char> b; vector<double> c; 所有C的标准库头文件都可以如此改换名称,在C++中使用(需要using namespace std);而且只有标准库头文件才可以如此改换名称,一般的头文件是不需要换的。其实“头文件”仅是一个约定的做法,#include是一个编译预处理指令,其意义仅在于指示编译器将被include的文件的内容粘贴到此处,所以即便你将头文件命名成xxx.ppt也能通过编译。 C语言原本没有逻辑类型,用0表示假,用非0表示真, C99标准新规定了一个逻辑类型_Bool,它在C++里面变成了bool。即便有了逻辑类型,在C++里面,仍然沿用“用0表示假,用非0表示真”的做法。 cin和cout是C++新定义的流输入输出方式,它们的用法是用“>>” 或“<<” (提取,插入)像串糖葫芦一样把变量串起来,被串起来的变量将按顺序被读入或输出,流输入输出方式将在最后做进一步的解释。 new和delete是C++引入的运算符,作用与C中的malloc和free相仿,不过到底是有区别的。 C中的字符串在C++中有了特性更完备的替代品string,C中的字符串在C++中被称作“C风格字符串”,仍然在发挥作用,不过很多时候是在与string配合使用。 vector是与C++中一个重要概念——容器的代表,vector可以看作长度可变的数组,很多时候代替了C数组。

即时声明和初始化方法 C语言要求所有变量的声明必须在实意语句之前,也就是在所有{}的外面,或者是每对{}的最前面。 This is the beginning. C语言要求所有变量的声明必须在实意语句之前,也就是在所有{}的外面,或者是每对{}的最前面。 C++没有了这样的限制,变量只要遵循先声明后使用的原则就可以了,不再要求必须放在什么地方。这就是为什么我们可以在for语句头部塞上一个int i(0)。 “int i(0)”里的(0)是指将i初始化为0,作用相当于int i=0。 但()的初始化方法不限于此: string a(“WindyWinter is talented.”); string b(a); string c = a; ()与=是否永远等价呢?对于内置类型是等价的,但对于类类型,一般是不等价的。 在所有{}外面的叫全局变量。 内置类型有bool, int, double等。 不等价性涉及到类的构造函数和拷贝构造函数,当讲完构造函数之后,我想大家就能完全明白()是什么意思了,但拷贝构造函数将被略过。

引用 引用(reference)是C++新定义的一种复合类型,其本意可以理解为变量的“别名(alternate name)”。 It’s something new. 引用(reference)是C++新定义的一种复合类型,其本意可以理解为变量的“别名(alternate name)”。 声明/定义一个引用: int a; int & r = a; r被定义为a的引用后,r和a可以被认为是同一个变量。 引用的主要用在函数形参中(作用与指针相仿): 避免传递规模巨大的实参; 将形参的值返回。 在C语言中我们已经见过一种很常用的复合类型——数组,任何类型,包括某个数组类型,加上一对方括号都可以构成一个新的数组类型;还有一个复合类型,是——指针。 注意,这里虽然有一个“=”,但却不是赋值运算符,而是“定义”。除非是函数形参列表中,否则引用的声明和定义必须在一起。 什么是声明?什么是定义? (作用与指针相仿)——形参与实参将共享同一个内存单元。 下面这个函数可以把a,b的值交换(注意这个函数写的不好,只是为了省地方才这么写)。 void swap(int & a, int & b) { a^=b^=a^=b; }

引用 指针 引用 The difference between reference and pointer 是一个变量(当然也可以加上const成为常量); 存在“空指针”; 取地址运算符,解引用运算符。 应用应当被看作一个“符号”,与const指针类似; 不存在“空引用”; 用法与正常变量一样。

左值与右值 左值 右值 Left or right, that is the question. 赋值运算符左边必须是左值; 变量皆是左值; 变量的引用是左值; string str是左值; ++i是左值; int *a = new int[10]; a是左值; 函数、表达式可以返回左值——以引用的形式。 赋值运算符右边既可以是左值,又可以是右值; 常量皆是右值; 常量的引用是右值; “WindyWinter is talented.”是右值; i++是右值; int a[10]; a是右值; 函数、表达式可以返回右值——以值的形式。 既然谈到了const和引用,就不得不提一个在C++中被强化的概念——左值和右值。这两个定义的来源是以赋值运算符为标准的。 左值既可以出现在赋值运算符的左边,也可以出现在右边;而右值只可以出现在右边。 注意左右两个a并不是同一个类型,左边是“指向整型的指针”,值是new运算符开辟的那个数组的首地址;右边是一个数组,数组本身并没有“值”的概念,但是在C和C++中,数组名可以转化为“指向数组的指针”,其值为数组的首地址。

函数 inline函数。 形参允许有默认值,即函数可以声明为如下形式: void func(int a, int b=0, int c=1); 如果在调用时没有给出b,c的值,则b=0,c=1,即调用时可以不写有默认值的参数——func(1), func(1,2), func(1,2,3)均是合法的。 允许不同的函数有相同的函数名(被称为函数重载)。 “不同的函数”是指形参的类型、数目或返回值的类型不同的函数,比如: int min(int a, int b); double min(double a, double b); int min(int a, int b, int c); double min(double a, double b, double c); 两两不同。 inline函数在C99标准里已有详细规定,内联函数的意义在于提示编译器,在调用该函数的地方可以直接把函数体粘贴过去,省去函数调用的开销;C++的inline函数与此基本相同。 有默认值的形参必须是该函数的最后一个或几个形参。 类型不同或数目不同均可,但若只有返回值类型不同则不行。

类型转换 C++继承了原有的C语言的隐式类型转换; We can change! – Change what? C++继承了原有的C语言的隐式类型转换; 所有的类型都可以隐式转换为该类型的引用: int => int &, int * => int * &, string => string &; 所有的类型都可以隐式转换为该类型的常量; C风格字符串可以隐式转换为const string; 强制类型转换在C++中有了另一类写法: (type) a  xxx_cast<type> a; static_cast<type>实现与C中类型转换相同的功能; const_cast<type>去掉表达式的常量性; 另外还有reinterpret_cast和dynamic_cast 隐式类型转换就是自动的类型转换,不需要显式的写出来的。C语言的隐式类型转换有哪些?哪种转换不是隐式的? C语言中一个带括号的类型名称后面跟一个表达式,表示将表达式的结果强制转换为指定的类型。 C++中对应的写法为xxx_cast<类型名>表达式。 注意const_cast应该慎用,后两种cast将不再涉及。

Tags Cloud Keywords 课程适用性 cstdlib namespace int main() bool cin cout new delete string vector 即时声明 初始化方法() 引用 左值和右值 inline 函数重载 形参默认值 类型转换 强制类型转换 www.google.com www.cplusplus.com/reference 我们休息一下,这是第一段的tag。今天讲的内容是非常简略的,建议大家以此为关键词,搜索相关资料。下面的两个网站是搜索的常用地点——第一个相信大家都认得,第二个可以当作C++的reference。 Have a break.

面向对象的C++ C++为此而生 在软件工程学提出面向对象的程序设计方法后,C被迅速扩充为Objected-C,这些内容后来成为C++的一部分。 在这一节中,我们只关注现象。

类 类是C++的新特性,为适应面向对象的程序设计而提出; 在C中,已经有了结构体的概念; Good morning class. 类是C++的新特性,为适应面向对象的程序设计而提出; 在C中,已经有了结构体的概念; 类与结构体的最大不同之处在于——不仅可以包含成员变量(常量),还可以包含成员函数。 当然,类还包括一些其他的特性: 成员变量、成员函数的访问权限; 构造函数; 析构函数; 拷贝构造函数; 隐式类型转换; …… 结构体在C中的实质是一堆变量的集合;在C++中,struct关键字仍然有效,但其意义已经改变——仅仅是另外一种声明一个类的方法。一个类应当被看作一种类型,这种类型声明的变量叫做对象,或者叫做这个类的实例。

一个著名的类 class person { private: string m_name; int m_age; string m_email; void update(); public: person(); ~person(); string get_namecard(); }; person Cindy; 我们给出一个类声明的例子。 声明一个类,用class关键字,样式和声明一个结构体是差不多的。不同的是多了private和public这两个关键字,他们被称作成员的访问权限。声明在public之下的成员用法与结构中的一样,在任何地方都可以直接访问这个成员;声明在private之下的成员,则只能被本类中的成员函数访问,在类外部是不可见的。不过,这一点我们很快就会做出修正。除了这两种访问权限之外,还有一种protected,后面也会讲到他的意义,protected成员的访问权限与private成员一致。 如果声明一个成员之前没有出现访问权限的标识,则默认为private。struct也可以声明一个类,与class的唯一区别是——struct中没有访问权限的成员默认为public。这么做的原因是令C代码可以无障碍的迁移到C++。 person类中,三个成员变量与update()函数均是private的,在类之外不能访问。get_namecard()是public的成员函数,可以在类外部被访问。 名称为person,没有返回值类型的那个东西,也是一个函数,叫做类的构造函数;名称为~person (tilde person)的函数叫做类的析构函数,马上就会讲到他们的作用。最后我们定义了一个person类型的对象,或者叫person类的实例。C中定义结构体类型的变量,要在结构名前面加struct关键字,C++中不再有结构体的概念,被统一为类,前面说过,类应当被视为一种类型,一个整体,故而声明类类型的变量直接用类的名字就可以了。

域运算符:: string person::get_namecard() { return m_name+m_email; } Well, one is just not enough. string person::get_namecard() { return m_name+m_email; } #include <iostream> int main() std::cout<<“Cindy is a smart girl.”<<std::endl; return 0; person类中声明了一个成员函数get_namecard(),那么,这个函数该怎么定义?一种方法是在声明的地方定义,另一种方法就是将定义写在类声明的外面,用域运算符,就是这两个冒号,指明get_namecard()是person的成员函数。 域运算符也可以用来指明某个标识符是定义在某个namespace中的。这样,可以不写using namespace xxx而引用该namespace下的标识符。 C++标准库的所有内容都统一声明在namespace std中。

this指针和成员函数的const属性 每个类都有一个特殊的“成员”——this,表示对象自身; This is my … self. 每个类都有一个特殊的“成员”——this,表示对象自身; this只能在该类的内部使用,与不指明this没有区别: this->m_name  m_name; this->update()  update(); 如果修改get_namecard()的声明为: string get_namecard() const ; get_namecard()将不能更改任何成员变量的值,在函数内部: this指针变成指向常量的指针; 任何成员变量被附加const属性。 这种声明主要用于指明该函数不会更改成员变量的值。 通常情况下,指明this和不指明this完全等价,不过存在特殊的情况,想必大家都遇到过,C语言里一个局部变量可以屏蔽全局变量,使得在局部变量的生存周期内被屏蔽的全局变量无效,(提问,有没有人知道是什么特殊情况了?)——某成员函数的形参恰好与类的成员变量同名,在该函数中,成员变量被形参屏蔽,访问时需要用this指针指明。 成员变量被附加的const属性实际上来自于this指针的常量性,其道理很浅显——一个常量实例的任何成员都是右值。这也说明,this指针的存在,是成员函数可以访问成员变量的原因,所以,上面的“与不指明this没有区别”,应该改为“不指明this与指明this没有区别”。 这样的声明,意在向别人说明,调用这个函数之后,成员变量不会发生任何变化。

构造函数 没有返回值类型,与类同名的函数被认为是构造函数; 它的作用就是——构造一个对象。 如何构造? constructor 没有返回值类型,与类同名的函数被认为是构造函数; 它的作用就是——构造一个对象。 如何构造? person() : m_name(“Cindy”), m_age(0) { … } person(const person & t) : m_name(t.m_name), m_age(t.m_age), m_email(t.m_email) { … } person(string name, int age) : m_name(name), m_age(age) { … } 冒号之后到括号之前,是构造函数特有的初始化列表,每一个成员变量用括号的形式初始化(只能用括号的形式),成员变量之间用逗号分隔。 这三个构造函数分别是不同类型的构造函数: 不带任何参数的叫默认构造函数,如果定义对象时,既没有使用括号的形式初始化,也没有使用=的形式初始化,那么默认构造函数将被调用; 带同类型引用或常量引用为参数的,叫拷贝构造函数,定义对象时,如果用=形式初始化,拷贝构造函数将被调用; 带其他类型参数的,是一般的构造函数,定义对象时,用括号的形式初始化,实际上就是调用对应的构造函数。 当前两种构造函数缺省时,编译器将自动合成缺省的构造函数: 对于内置类型的成员变量,缺省默认构造函数不做任何事情,缺省拷贝构造函数复制其值; 对于类类型的成员变量,缺省默认构造函数将调用该成员变量的默认构造函数,缺省拷贝构造函数调用该成员的拷贝构造函数, 若该成员变量的默认构造函数或拷贝构造函数不可用(下面将会说明为什么不可用),那么将无法通过编译。 不能显式调用构造函数——即构造函数只会在对象定义时被调用一次,今后再无它途。

构造函数 如果将某个构造函数声明为private,则这个构造函数将无法使用。一般来说,这样做的目的是阻止编译器生成缺省的构造函数。 It’s something not that new. 如果将某个构造函数声明为private,则这个构造函数将无法使用。一般来说,这样做的目的是阻止编译器生成缺省的构造函数。 只带有一个参数的构造函数表明了一种可能的隐式类型转换: string(const char * s); new与malloc的区别在于:前者创建对象,后者分配空间。 编译器合成的缺省构造函数有时在编程上带来很多麻烦。 这个构造函数提供了一个C风格字符串到string的隐式类型转换。 分配空间后,该空间的内部结构仍然是不明确的,只有在上面调用过构造函数,一个对象才被真正的创建出来。new运算符将在分配出来的空间上调用构造函数,malloc却无此功能,因此,C++中一般不再使用malloc。

析构函数 没有返回值,名字是~<class name>,没有参数的函数是析构函数。构造函数可以有多个,析构函数只能有一个。 destructor 没有返回值,名字是~<class name>,没有参数的函数是析构函数。构造函数可以有多个,析构函数只能有一个。 它的作用是销毁一个对象。 如果没有声明析构函数,编译器将合成默认析构函数: 对于内置类型,释放其空间; 对于类类型,调用其析构函数。 实际上,上面两步是编译器附加在任何析构函数最后的两步。因为没有办法显式“释放空间”和调用析构函数。 析构函数只能在delete时和离开该对象的生存域时被自动调用。 也存在将析构函数声明为private的情况。 tilde 这也是delete和free的区别,delete将调用析构函数,销毁对象;free只是释放空间。注意,不能用free释放new出来的对象占据的空间。 在析构函数被声明为private的情况下,只能通过友元和静态成员函数来控制对象的生成销毁。所以,将析构函数声明为private诣在阻止用户控制对象的生存周期,封堵在栈上创建对象的途径。其标准用途是对象池。(这段话有人听懂了吗?听懂的举手?)没听懂是正常的,听懂也没什么用,不过我不会阻拦硬要听懂的同学。

静态成员 Steady, steady… static关键字也可以修饰类的成员: class person { … static int population; static int get_population(); }; 被修饰的成员叫做类的静态成员,是这个类的属性,不是某个对象的属性。 访问用:: int person::population = 0; person::get_population(); C里面的static修饰符表示变量被创建在静态存储区,生存周期为整个程序运行时。 静态存储区是什么?(C/C++的三大存储区——静态存储区、栈、堆) 不能用成员运算符.访问。不在构造函数中初始化,不在析构函数中被撤销。 在静态成员函数中,不存在this指针,不能访问类的非静态成员。这里再次说明了this指针的存在是成员函数可以访问成员的原因。

运算符重载 C++不仅提供了对函数的重载,也提供了对运算符的重载。运算符可以视为特殊的函数。一个简单的运算符重载如下: It’s fully operational. C++不仅提供了对函数的重载,也提供了对运算符的重载。运算符可以视为特殊的函数。一个简单的运算符重载如下: 单目运算符: T1 operator [] (T2 a); int & operator [] (int i); 双目运算符: T1 operator < (T2 a, T3 b); bool operator < (person & a, person & b); 特别的运算符重载:++、--。 虽然可以视为函数,但只能重载已经存在的运算符,不能自定义新的运算符。 不能重载内置类型之间的运算符。 自增、自减运算符特殊,是因为他们在表达式之前与表达式之后表示的意义并不完全相同。他们的重载方法请诸位自行查找相关资料,并不复杂,只是需要区分。 这里讲的运算符重载是非常简单的,最简单的情况。

运算符重载 还有一类特殊的运算符也可以被重载: opetator T() operator int(); operator xxx(); 这样的运算符必须是某个类的成员函数,它为这个类提供向特定类型的隐式类型转换。比如: class person { … string operator string(); } 更多的很多情况下,运算符重载是一个复杂的工程。在你真正掌握重载之前,请慎用。 更多的运算符重载,请查找专业教材。

继承与派生 class tallent : public person { … int IQ; }; Kim Jong-il chooses his third son as successor. class tallent : public person { … int IQ; }; 上面定义了person类的一个派生类tallent类,它将获得person类的一切成员,还另外附加了一个IQ成员。 上面的“一切成员”,不包括基类的构造函数、析构函数、new运算符和=运算符。但派生类中可以访问他们。 派生类对象可以隐式转换为基类类型; 派生类类型的指针可以隐式转换为基类类型的指针; person * WindyWinter = new tallent; person类被称为基类。 与之相对的是,派生类与基类是不同的类,派生类获得基类的私有成员,但不能访问基类的私有成员。 public关键字表示继承的访问关系控制,类似还有private继承和protected继承。 在private继承中,基类的public成员和protected成员成为派生类的private成员; 在protected继承中,基类的public成员和protected成员成为派生类的protected成员; 在public继承中,基类的成员的访问权限不变。 说指针可以隐式转换是不太正确的,这里表现起来的确像是类型转换,但事实上WindyWinter指针仍然保持了tallent的特性。

虚函数与多态 在声明某个成员函数时加上virtual修饰符,表示允许派生类重载该函数;在声明析构函数时加上virtual修饰符,产生特殊效果。 class person { … virtual string get_namecard(); }; WindyWinter->get_namecard(); virtual string get_namecard() = 0; 虚析构函数与销毁派生类中的指针的机制有关。 WindyWinter虽然是person类型指针,但调用的get_namecard()函数却是tallent类的重载版本。这一特性叫做多态。 虚函数的“虚”是翻译的结果,他们是真实存在的函数,要想让它不存在,变成真正的“虚”函数,要在声明后面加“=0”,这样的虚函数叫纯虚函数,他只有一个声明,没有定义,不能被调用。带有纯虚函数的类不能用来定义对象,派生类如果不重载这个纯虚函数,一样不能定义对象。

多继承 一个类可以继承于多个类,派生类获得所有基类的成员。 Well, one is just not enough. 一个类可以继承于多个类,派生类获得所有基类的成员。 class tallent : public person, public another_person { … int IQ; }; 基类之间用逗号分隔。 如果两个基类有同名成员,将在派生类中产生二义性,需要用::做访问控制。

友元 A friend in need is a friend indeed. class tallent { … friend smart_girl; friend bool pay(); friend bool dreamland::login(); friend tallent operator +(…); }; 友元需要声明在类的public段之下。 友元是一个声明。友元不是类的成员。 有时我们需要在类外部访问类的private成员,这时需要声明一个类的友元。友元可以是另外一个类,可以是函数,可以是某个类的成员函数,也可以是运算符。被声明为友元的东西可以访问这个类的private成员。 这意味着:1. 友元的声明要按声明的完整格式写,还要附加friend修饰符; 2. 友元不在声明友元的地方定义,在另外的地方定义。

Tags Cloud 类 域运算符 构造函数 析构函数 this指针 静态成员 静态成员函数 友元 Keywords 类 域运算符 构造函数 析构函数 this指针 静态成员 静态成员函数 友元 继承 派生 多继承 虚函数 纯虚函数 多态 运算符重载 类型转换 OOP 虚继承 我们休息一下,这是第二段的tag。今天讲的内容是非常简略的,建议大家以此为关键词,搜索相关资料。最后的两个关键词今天没有讲到。OOP的概念非常重要,不过这是一个非常理论化的东西,平时写程序未必需要理解;虚继承是较为特殊的一种继承。

作业 在这里结束 留一点作业,然后大家就解放了。

作业 Soli Deo gloria. USTC OnlineJudge 1000 1001 1003 1004 Homework 以上题目是锻炼编程语言熟练度的题目。不要求全部做完,也不检查作业。 今天就到这里吧,感谢大家捧场。Soli Deo gloria. 最后我给大家演示一下如何在USTC OnlineJudge上做题。如果对今天的内容还有疑议,请立刻提出。 Soli Deo gloria.