PowerPoint Presentation

Similar documents
C/C++程序设计 - 字符串与格式化输入/输出

Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式]

02

WWW PHP

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

c_cpp

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf ("%d", & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9

chap07.key

C/C++ - 函数

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

Strings

ebook50-15

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

C/C++ - 文件IO

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式]

Windows XP

Microsoft PowerPoint - ch6 [相容模式]

Microsoft Word - template.doc

CC213

C/C++ 语言 - 循环

untitled

酒 神 (长篇小说)

(Microsoft Word - 136\260g\270\364\252\272\267s\256Q.doc)

C/C++ - 字符串与字符串函数

说 : 荀 子 极 偏 驳, 只 一 句 性 恶, 大 本 已 失 5 朱 熹 说 : 荀 扬 不 惟 说 性 不 是, 从 头 到 底 皆 不 识 6 采 取 的 都 是 这 种 理 论 框 架 另 一 种 理 论 框 架 始 于 20 世 纪 前 期, 这 便 是 诸 子 学 研 究 的 框 架

2013 C 1 #include <stdio.h> 2 int main(void) 3 { 4 int cases, i; 5 long long a, b; 6 scanf("%d", &cases); 7 for (i = 0; i < cases; i++) 8 { 9 scanf("%

C/C++语言 - C/C++数据

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

extend

untitled

C++ 程式設計

Chapter12 Derived Classes

Eclipse C C++, or

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

C/C++ - 字符输入输出和字符确认

Microsoft PowerPoint - L17_Inheritance_v4.pptx

新版 明解C++入門編

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco

不 知 肉 味 的 用 法 相 同? (A) 長 煙 一 空, 皓 月 千 里 (B) 五 臟 六 腑 裡, 像 熨 斗 熨 過, 無 一 處 不 伏 貼 (C) 兩 片 頑 鐵, 到 他 手 裡, 便 有 了 五 音 十 二 律 似 的 (D) 吾 觀 三 代 以 下, 世 衰 道 微 12. 文

PowerPoint Presentation

untitled

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

BC04 Module_antenna__ doc

C

UDC Empirical Researches on Pricing of Corporate Bonds with Macro Factors 厦门大学博硕士论文摘要库

Microsoft PowerPoint - string_kruse [兼容模式]

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

无类继承.key

2

翻 那 本 日 记, 好 像 和 自 己 赌 气, 好 像 那 个 人 还 在 乎 一 样, 里 面 的 内 容, 因 为 在 较 着 劲, 就 是 不 愿 意 去 看 那 些 甜 蜜 的 过 往 小 小 的 日 记 本 塞 在 行 李 箱 的 底 部, 安 静 地 呆 在 那 儿, 只 是, 不

untitled

(baking powder) 1 ( ) ( ) 1 10g g (two level design, D-optimal) 32 1/2 fraction Two Level Fractional Factorial Design D-Optimal D

untitled

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

<4D F736F F D20AE61AC462DBFAFADB9AD70B565BB50BB73A740B1D0AED7>

WFC40810

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

ebook14-4

EK-STM32F

《80后职场新鲜人生存手册》

<4D F736F F D205F FB942A5CEA668B443C5E9BB73A740B5D8A4E5B8C9A552B1D0A7F75FA6BFB1A4ACFC2E646F63>

Microsoft Word - (web)_F.1_Notes_&_Application_Form(Chi)(non-SPCCPS)_16-17.doc

WVT new

Microsoft PowerPoint - 10 模板 Template.pptx

Microsoft Word - 01.DOC

Microsoft Word - 第3章.doc


Logitech Wireless Combo MK45 English

1. 請 先 檢 查 包 裝 內 容 物 AC750 多 模 式 無 線 分 享 器 安 裝 指 南 安 裝 指 南 CD 光 碟 BR-6208AC 電 源 供 應 器 網 路 線 2. 將 設 備 接 上 電 源, 即 可 使 用 智 慧 型 無 線 裝 置 進 行 設 定 A. 接 上 電 源

Microsoft Word - 論文封面 修.doc

Microsoft Word cppFinalSolution.doc

Microsoft Word

提纲 1 2 OS Examples for 3

Microsoft Word 軟體設計第二部份範例試題_C++_ _1_.doc

新北考區105年國中教育會考簡章

FY.DOC

105 年 國 中 教 育 會 考 重 要 日 期 項 目 日 期 及 時 間 報 名 1. 集 體 報 名 :105 年 3 月 10 日 ( 星 期 四 ) 至 3 月 12 日 ( 星 期 六 ) 每 日 8:00~12:00 13:30~17:00 2. 個 別 報 名 : 於 上 網 填

93年度推薦甄選考古題

國立桃園高中96學年度新生始業輔導新生手冊目錄

<4D F736F F D203338B4C12D42A448A4E5C3C0B34EC3FE2DAB65ABE1>

〇〇考區105年國中教育會考簡章

C++ 程序设计 实验 2 - 参考答案 MASTER 2017 年 5 月 21 日 1

第3章.doc

untitled

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

C++ 程序设计 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

( ) 16. 老 年 人 因 老 化 現 象 導 致 聽 力 較 差, 溝 通 時 應 以 高 頻 率 音 調 說 話 較 佳 編 碼 :01743 出 處 :0105 來 源 : 課 本 ( ) 17. 老 年 人 因 為 對 甜 鹹 的 味 覺 遲 鈍, 因 此 口 味 會 偏 重 此 時 可

PowerPoint Presentation

中国科学技术大学学位论文模板示例文档

Microsoft Word - 物件導向編程精要.doc

IO

第七讲 继承与多态

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

EJB-Programming-4-cn.doc

ENGG1410-F Tutorial 6

C

K301Q-D VRT中英文说明书141009

二 痛 苦 的 记 忆 在 莫 七 七 有 记 忆 以 来, 家 里 似 乎 每 天 都 上 演 着 全 武 行, 没 有 一 天 安 静 过 的 她 不 知 道 为 什 么, 别 人 的 爸 爸 妈 妈 都 那 么 好, 会 宠 自 己 的 小 孩, 而 她 的 爸 爸 妈 妈 只 会 把 她 当

Transcription:

USTC Chapter 8 Technicalities: Functions, etc. 王子磊 (Zilei Wang) Email: zlwang@ustc.edu.cn http://vim.ustc.edu.cn

Overview 本章和下一章将对 C++ 编程语言的一些技术细节进行探讨, 并进行系统化说明 本章概览 编程语言技术细节 声明 Declarations 定义 头文件与预处理 作用域 函数 Functions 声明和定义 参数 调用 : 传值 传引用 传常量 (const) 引用 命名空间 using 声明和指令

编程语言技术细节 这是必要的 编程语言是一门外语 当你学习一门外语时, 需要研究它的语法和词汇 这就是本章和下一章要做的事情 因为 : 程序必须被精确和完整地描述 计算机是一个非常 愚蠢 的机器 ( 尽管它很快 ) 计算机不能猜测出你 说的真正意思 ( 也不应该这样做 ) 因此, 我们必须学习规则 实际上仅学习其中的一部分 (C++ 标准有 782 页之多 ) 然而, 永远不要忘记 我们真正学习的是编程 我们要产出的是程序和系统 编程语言仅仅是一个工具

关于技术细节 不要花费太多的时间在语法和语义细节问题上 表达和解决一个问题总是有多种形式 就像我们的文字语言一样 多数的设计和编程概念是通用的 至少是被几种流行的编程语言广泛支持的 因此, 我们在 C++ 中学习到的东西也可以用在其他语言上 编程语言技术细节是针对给定语言特有的 不过,C++ 语言提供的绝大部分技术特征在其他语言 ( 如 C, Java, C#, etc) 中都有明显对应的内容

声明 Declarations 声明将一个名称引入到作用域中 声明为命名对象指定了一个类型 有时, 声明还进行初始化 在 C++ 中, 名称只有声明以后才能够使用 示例 : int a = 7; // an int variable named a is declared const double cd = 8.7; // a double-precision floating-point constant double sqrt(double); // a function taking a double argument and // returning a double result vector<token> v; // a vector variable of Tokens (variable)

声明 Declarations 声明通常是通过一个 头 ( 文件 ) 引入到一个程序中 一个 头 是一个包含声明的文件, 它提供了程序中其它部分的访问接口 这为 抽象 提供了可能 你不必知道函数的细节, 而只需像 cout 那样使用即可 如果添加 #include "../../std_lib_facilities.h" 到你的代码中, 文件 std_lib_facilities.h 中的声明对你就是可用的 ( 包括 cout 等 )

定义 Definitions 如果声明还给出了声明实体 ( 实现 ) 的完整描述, 则称之为定义 定义是一种特殊的声明, 但声明不一定是定义 定义示例 : int a = 7; int b; // an int with the default value (0) vector<double> v; // an empty vector of doubles double sqrt(double) { }; // i.e. a function with a body struct Point { int x; int y; }; 是声明而不是定义的示例 : double sqrt(double); struct Point; // function body missing extern int a;// extern means not definition 过时的, 基本不用了! // class members specified elsewhere // extern is archaic; we will hardly use it

声明与定义 你不能定义一个对象两次 定义说明了它是什么 ( 会分配内存进行存储 ) 例如 : int a; // definition int a; // error: double definition double sqrt(double d) { } // definition double sqrt(double d) { } // error: double definition 但可以声明一个对象多次 声明仅说明了它如何被使用 ( 非定义不分配内存 ) int a = 7; // definition (also a declaration) extern int a; // declaration double sqrt(double); // declaration double sqrt(double d) { } // definition (also a declaration)

为什么声明和定义都需要呢? 为了引用一个对象, 只需要包括它的声明就可以了 大部分情况下, 我们想在其他地方对它进行定义 一个文件的后面部分 在另一个文件里 甚至可能是其他人编写的 声明用于指定接口 你自己的代码 程序库 对程序库是关键的 : 我们不能也不愿意自己写全部代码 在较大的程序中 将所有相关的声明放在头文件中, 以便于共享

头文件和预处理 头 是包含函数 类型 常量或其他程序组件声明的一个文件 下面的结构 #include "../../std_lib_facilities.h" 是一个 预处理 指令 简单地将头文件中的声明复制到文件的 #include 指令处 头文件是简单的文本文件 头 提供了函数 类型等的访问接口, 你可以在自己的程序中使用它们 通常, 你不需要关心它们是如何实现的 实际的函数 类型等在其他源文件中进行定义 通常是程序库的一部分 头文件只能包含那些可以在多个文件中重复多次的声明 ( 函数声明 类定义和数据常量定义 ) 考虑一下, 若头文件中有定义, 如何在多个文件 #include 时避免重复定义错误?

源文件 token.cpp: token.h: // declarations: class Token { }; class Token_stream { Token get(); }; #include "token.h" //definitions: Token Token_stream::get() { /* */ } use.cpp: #include "token.h" Token t = ts.get(); 头文件 ( 此处的 token.h) 定义了用户代码和实现代码之间的接口 通常是在一个库中 在所有.cpp 文件 ( 定义和使用 ) 中使用同样的 #include 声明有利于一致性检查

作用域 Scope 作用域是一个程序文本的区域 编译器特性 例如 : 全局作用域 ( 任何其他作用域之外的区域 ) 类作用域 ( 在一个类内 ) 局部作用域 ( 在花括号 { } 之间 ) 语句作用域 (e.g. for 语句 ) 一个作用域的名称对该作用域和嵌套内的作用域是可见的 当然, 必须在名称声明之后 ( 不能先用 规则 ) 作用域使 实体 (things) 是局部的 避免我的变量 函数等实体与你的发生冲突 谨记 : 实际的程序中有成千上万个实体 局部性是最好的! 尽量使名称局部化

作用域 #include "std_lib_facilities.h" // no r, i, or v here class My_vector { vector<int> v; public: int largest() { int r = 0; for (int i = 0; i<v.size(); ++i) r = max(r,abs(v[i])); // no i here return r; } // no r here }; // no v here // get max and abs from here // v is in class scope // largest is in class scope // r is local // i is in statement scope

作用域嵌套 int x; // global variable avoid those where you can int y; // another global variable 0 int f() { int x; x = 7; { } // x = 7; } // x = 0; 存在初始化顺序不确定 修改定位困难等问题 // local variable (Note now there are two x s) // local x, not the global x int x = y; // another local x, initialized by the global y // (Now there are three x s) 0 x++; // increment the local x in this scope 1 本质上, 编译器对不同作用域有不同的命名 尽可能避免这么复杂的嵌套 :keep it simple!

函数 一般形式 : return_type name (formal arguments); // a declaration return_type name (formal arguments) body // a definition 例如 : double f(int a, double d) { return a*d; } 形参通常也称作参数 如果你不想返回任何值, 使用 void 作为返回类型 void increase_power(int level); 这里, void 意思是 不返回一个值 函数体是一个程序块或 try 块 例如 : { /* code */ } // a block try { /* code */ } catch(exception& e) { /* code */ } 函数实现 ( 表示 ) 了实际的计算功能 返回值可以看做为初始化的另一种形式 // a try block

函数 : 传值 // call-by-value (send the function a copy of the argument s value) int f(int a) { a = a+1; return a; } a: 0 int main() { xx: int xx = 0; cout << f(xx) << endl; // writes 1 cout << xx << endl; // writes 0; f() doesn t change xx int yy = 7; cout << f(yy) << endl; // writes 8; f() doesn t change yy cout << yy << endl; // writes 7 } 0 copy the value a: 7 copy the value 代价 : 拷贝值 yy: 7

函数 : 传引用 // call-by-reference (pass a reference to the argument) int f(int& a) { a = a+1; return a; } int main() { int xx = 0; cout << f(xx) << endl; // writes 1 // f() changed the value of xx cout << xx << endl; // writes 1 int yy = 7; cout << f(yy) << endl; // writes 8 // f() changes the value of yy cout << yy << endl; // writes 8 a: 1 st call (refer to xx) xx: yy: 0 2 nd call (refer to yy) 7 } 引用拷贝代价低, 只需一个地址引用即可!

函数 尽量避免使用传引用参数 (non-const) 当你忘记那些参数能够修改时, 它会导致一些莫名的 bugs int incr1(int a) { return a+1; } void incr2(int& a) { ++a; } int x = 7; x = incr1(x); // pretty obvious incr2(x); // pretty obscure 那为什么还需要引用参数呢? 在一些情况下, 它是重要的 e.g., 改变多个参数的值 操作容器 (e.g., vector) const 引用更常用

传值 传引用和传常量引用 void f(int a, int& r, const int& cr) { ++a; ++r; ++cr; } // error: cr is const void g(int a, int& r, const int& cr) { ++a; ++r; int x = cr; ++x; } // ok int main() { int x = 0; int y = 0; int z = 0; g(x,y,z); g(1,2,3); g(1,y,3); } // x==0; y==1; z==0 // error: reference argument r needs a variable to refer to // ok: since cr is const we can pass a temporary const 引用更常用, 主要用于传递较大的对象

引用 引用 是个一般性概念 不仅仅用于函数的传引用 r int i = 7; int& r = i; r = 9; // i becomes 9 cr const int& cr = i; // cr = 7; // error: cr refers to const i = 8; cout << cr << endl; // write out the value of i (that s 8) 可以认为引用是一个对象的别名! 但你不能 通过一个 const 引用来修改一个对象 初始化后再将引用指向另一个对象 ( 赋值操作 ) i: 7

参数传递指导 使用传值方式传递较小的对象 使用传 const 引用方式传递你不需要修改的大对象 让函数返回一个结果值, 而不是修改通过引用传递来的对象 ( 尽量 ) 只在必要的时候才使用传引用调用 ( 非 const) 例如 : class Image { /* objects are potentially huge */ }; void f(image i); f(my_image); // oops: this could be s-l-o-o-o-w void f(image& i); f(my_image); // no copy, but f() can modify my_image void f(const Image&); f(my_image); // f() won t mess with my_image 更多函数参数和实现的内容参看课本的 8.5 节

名字空间 考虑下面来自两个不同程序员 (Jack 和 Jill) 的代码 class Glob { /* */ }; class Widget { /* */ }; class Blob { /* */ }; class Widget { /* */ }; // in Jack s header file jack.h // also in jack.h // in Jill s header file jill.h // also in jill.h #include "jack.h"; #include "jill.h"; // this is in your code // so is this void my_func(widget p) { // } // oops! error: multiple definitions of Widget 变量的重定义

名字空间 编译器不能编译通过多重定义的变量 在使用多个头文件时, 这种冲突可能会发生 避免这种情况的一种有效方式是使用名字空间 namespace Jack { // in Jack s header file class Glob{ /* */ }; class Widget{ /* */ }; } #include "jack.h"; #include "jill.h"; // this is in your code // so is this void my_func(jack::widget p) // OK, Jack s Widget class will not { // clash with a different Widget // }

名字空间 名字空间是一个命名的作用域 不需要定义类型就可以拥有一个可访问的作用域 :: 语法用于指定使用的名字空间名称和对象名称 例如 : cout 在名字空间 std 中, 你可以写成下面的形式 : 本质上 std::cout << "Please enter stuff \n ; 名字空间是让编译器将对象编译为一个不同的 id (id 依赖于作用域和对象名字 )

using 声明和指令 为了避免下面的冗长 std::cout << "Please enter stuff \n"; 你可以使用一个 using 声明 using std::cout; // when I say cout, I mean std::cout cout << "Please enter stuff \n"; // ok: std::cout cin >> x; // error: cin not in scope 或者, 直接使用 using 指令 using namespace std; // make all names from namespace std available cout << "Please enter stuff \n"; // ok: std::cout cin >> x; // ok: std::cin 将一个 using 指令放在头文件中是一个非常坏的习惯!

Next 关于类的更多技术细节