《第三章 命名空间精选PPT.ppt》由会员分享,可在线阅读,更多相关《第三章 命名空间精选PPT.ppt(20页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第三章 命名空间第1页,本讲稿共20页本章主要内容l l编译单元、内部连接与外部连接编译单元、内部连接与外部连接l l命名空间的概念命名空间的概念l l命名空间的定义和使用命名空间的定义和使用l l命名空间的别名命名空间的别名 l lKoenig查找规则查找规则2023/1/172023/1/172 2第2页,本讲稿共20页控制连接控制连接(1)编译单元)编译单元(2)内部连接)内部连接(3)外部连接)外部连接 2023/1/172023/1/173 3第3页,本讲稿共20页编译单元编译单元l l当一个当一个c或或cpp文件在编译时,预处理器首先文件在编译时,预处理器首先递归包含头文件,形成一
2、个含有所有递归包含头文件,形成一个含有所有 必要信必要信息的单个源文件息的单个源文件,这个源文件这个源文件 就是一个编译单就是一个编译单元。这个编译单元会被编译成为一个与元。这个编译单元会被编译成为一个与cpp文文件名同名的目标文件件名同名的目标文件(.o或是或是.obj)。连接程序。连接程序把不同编译单元中产生的符号联系起把不同编译单元中产生的符号联系起 来,构来,构成一个可执行程序。成一个可执行程序。2023/1/172023/1/174 4第4页,本讲稿共20页内部连接内部连接(1)内部连接:如果一个名称对于它的编译单)内部连接:如果一个名称对于它的编译单元来说是局部的,并且在连接时不会
3、与其它编元来说是局部的,并且在连接时不会与其它编译单元中的同样的名称相冲突,那么这个名称译单元中的同样的名称相冲突,那么这个名称有内部连接有内部连接(注:有时也将声明看作是无连接注:有时也将声明看作是无连接的,这里我们统一看成是内部连接的的,这里我们统一看成是内部连接的)。2023/1/172023/1/175 5第5页,本讲稿共20页内部连接内部连接(2 2)以下情况有内部连接)以下情况有内部连接)以下情况有内部连接)以下情况有内部连接:l l所有的声明。所有的声明。所有的声明。所有的声明。l l名字空间名字空间名字空间名字空间(包括全局名字空间包括全局名字空间包括全局名字空间包括全局名字空
4、间)中的静态自由函数、中的静态自由函数、中的静态自由函数、中的静态自由函数、静态友元函数、静态变量的定义。静态友元函数、静态变量的定义。静态友元函数、静态变量的定义。静态友元函数、静态变量的定义。l lenumenum定义。定义。定义。定义。l linlineinline函数定义函数定义函数定义函数定义(包括自由函数包括自由函数包括自由函数包括自由函数 和非自由函数和非自由函数和非自由函数和非自由函数)。l l类的定义。类的定义。类的定义。类的定义。l l名字空间中名字空间中名字空间中名字空间中constconst常量定义。常量定义。常量定义。常量定义。l lunionunion的定义。的定义
5、。的定义。的定义。2023/1/172023/1/176 6第6页,本讲稿共20页外部连接外部连接(1)外部连接:在一)外部连接:在一 个多文件程序中,如果一个多文件程序中,如果一个名称在连接时可以和其它编译单元交互,那个名称在连接时可以和其它编译单元交互,那么这个名称就有外部连接。么这个名称就有外部连接。2023/1/172023/1/177 7第7页,本讲稿共20页外部连接外部连接(2 2)以下情况有外部连接)以下情况有外部连接)以下情况有外部连接)以下情况有外部连接:l l类非类非类非类非inlineinline函数总有外部连接。包括类成员函数和类静态成员函数总有外部连接。包括类成员函数
6、和类静态成员函数总有外部连接。包括类成员函数和类静态成员函数总有外部连接。包括类成员函数和类静态成员函数。函数。函数。函数。l l类静态成员变量总有外部连接。类静态成员变量总有外部连接。类静态成员变量总有外部连接。类静态成员变量总有外部连接。l l名字空间名字空间名字空间名字空间(包括全局名字空间包括全局名字空间包括全局名字空间包括全局名字空间)中非静态自由函数、非中非静态自由函数、非中非静态自由函数、非中非静态自由函数、非静态友元函数及非静态变量。静态友元函数及非静态变量。静态友元函数及非静态变量。静态友元函数及非静态变量。2023/1/172023/1/178 8第8页,本讲稿共20页内部
7、连接与外部连接内部连接与外部连接注意:注意:注意:注意:对于全局变量和函数,定义时如果对于全局变量和函数,定义时如果指定是指定是static,则是内部连接;指定,则是内部连接;指定extern,是外部连接。默认为,是外部连接。默认为extern。2023/1/172023/1/179 9第9页,本讲稿共20页命名空间的概念命名空间的概念l lC C语言中的预处理、静态处理等会引起语言中的预处理、静态处理等会引起语言中的预处理、静态处理等会引起语言中的预处理、静态处理等会引起命名冲突命名冲突命名冲突命名冲突。l l命名空间命名空间命名空间命名空间(也叫名字空间、名称空间)是用来限定名称的解析和使
8、(也叫名字空间、名称空间)是用来限定名称的解析和使(也叫名字空间、名称空间)是用来限定名称的解析和使(也叫名字空间、名称空间)是用来限定名称的解析和使用范围的,以解决命名冲突。用范围的,以解决命名冲突。用范围的,以解决命名冲突。用范围的,以解决命名冲突。l l命名空间是一个逻辑上的类型组织系统,用它来对程序中的类命名空间是一个逻辑上的类型组织系统,用它来对程序中的类命名空间是一个逻辑上的类型组织系统,用它来对程序中的类命名空间是一个逻辑上的类型组织系统,用它来对程序中的类型进行逻辑上的分组,并使定义在同一个命名空间中的类可利型进行逻辑上的分组,并使定义在同一个命名空间中的类可利型进行逻辑上的分
9、组,并使定义在同一个命名空间中的类可利型进行逻辑上的分组,并使定义在同一个命名空间中的类可利用命名空间直接相互调用。用命名空间直接相互调用。用命名空间直接相互调用。用命名空间直接相互调用。l l标准的标准的标准的标准的C+C+有命名空间机制,使用有命名空间机制,使用有命名空间机制,使用有命名空间机制,使用namespacenamespace关键字。库或程序关键字。库或程序关键字。库或程序关键字。库或程序中的每一个中的每一个中的每一个中的每一个C+C+定义集被封装在一个命名空间中,如果其他的定义定义集被封装在一个命名空间中,如果其他的定义定义集被封装在一个命名空间中,如果其他的定义定义集被封装在
10、一个命名空间中,如果其他的定义中有相同的名字,但它们在不同的命名空间,则不会产生命名冲突。中有相同的名字,但它们在不同的命名空间,则不会产生命名冲突。中有相同的名字,但它们在不同的命名空间,则不会产生命名冲突。中有相同的名字,但它们在不同的命名空间,则不会产生命名冲突。2023/1/172023/1/171010第10页,本讲稿共20页命名空间的定义命名空间的定义格式:格式:格式:格式:namespacenamespace 命名空间命名空间命名空间命名空间名名名名 /命名空间成员(其他命名空间或类的定义)命名空间成员(其他命名空间或类的定义)命名空间成员(其他命名空间或类的定义)命名空间成员(
11、其他命名空间或类的定义)说明:说明:说明:说明:命名空间只能在全局范围内定义。命名空间只能在全局范围内定义。命名空间只能在全局范围内定义。命名空间只能在全局范围内定义。“命名空间名命名空间名命名空间名命名空间名”是是是是C+C+合法的标识符,也可以是用作用域分合法的标识符,也可以是用作用域分合法的标识符,也可以是用作用域分合法的标识符,也可以是用作用域分解运算符(解运算符(解运算符(解运算符(:)来构成的命名空间的完全限定名。可以没)来构成的命名空间的完全限定名。可以没)来构成的命名空间的完全限定名。可以没)来构成的命名空间的完全限定名。可以没有命名空间名(有命名空间名(有命名空间名(有命名空
12、间名(无名的命名空间无名的命名空间无名的命名空间无名的命名空间),其成员的名称不需),其成员的名称不需),其成员的名称不需),其成员的名称不需要限定就可以使用。要限定就可以使用。要限定就可以使用。要限定就可以使用。不允许在定义命名空间时使用任何访问修饰符。系统默认不允许在定义命名空间时使用任何访问修饰符。系统默认不允许在定义命名空间时使用任何访问修饰符。系统默认不允许在定义命名空间时使用任何访问修饰符。系统默认命名空间具有命名空间具有命名空间具有命名空间具有publicpublic访问属性。但可以在一个命名空间的访问属性。但可以在一个命名空间的访问属性。但可以在一个命名空间的访问属性。但可以在
13、一个命名空间的类定义中插入一个友元声明。类定义中插入一个友元声明。类定义中插入一个友元声明。类定义中插入一个友元声明。命命名名空空间间的的定定义义和和使使用用2023/1/172023/1/171111第11页,本讲稿共20页命名空间的定义命名空间的定义说明(续):说明(续):说明(续):说明(续):命名空间的成员可以是另一个命名空间(嵌套)或类型(类、命名空间的成员可以是另一个命名空间(嵌套)或类型(类、命名空间的成员可以是另一个命名空间(嵌套)或类型(类、命名空间的成员可以是另一个命名空间(嵌套)或类型(类、结构、接口、枚举等)的定义。结构、接口、枚举等)的定义。结构、接口、枚举等)的定义
14、。结构、接口、枚举等)的定义。一个命名空间可以在多个头文件中用一个标识符来定一个命名空间可以在多个头文件中用一个标识符来定一个命名空间可以在多个头文件中用一个标识符来定一个命名空间可以在多个头文件中用一个标识符来定义,就好像重复定义一个类一样。义,就好像重复定义一个类一样。义,就好像重复定义一个类一样。义,就好像重复定义一个类一样。一个命名空间的名字可以用另一个名字来作它的别名,一个命名空间的名字可以用另一个名字来作它的别名,一个命名空间的名字可以用另一个名字来作它的别名,一个命名空间的名字可以用另一个名字来作它的别名,这样就不必敲打那些开发商提供的冗长的名字了。这样就不必敲打那些开发商提供的
15、冗长的名字了。这样就不必敲打那些开发商提供的冗长的名字了。这样就不必敲打那些开发商提供的冗长的名字了。不能像类那样去创建一个命名空间的实例。不能像类那样去创建一个命名空间的实例。不能像类那样去创建一个命名空间的实例。不能像类那样去创建一个命名空间的实例。可以在一个编译单元中包含一个未命名的命名空间,但只可以在一个编译单元中包含一个未命名的命名空间,但只可以在一个编译单元中包含一个未命名的命名空间,但只可以在一个编译单元中包含一个未命名的命名空间,但只能包含一个未命名的命名空间。能包含一个未命名的命名空间。能包含一个未命名的命名空间。能包含一个未命名的命名空间。在命名空间的结尾,右花括号的后面可
16、以跟一个分号(在命名空间的结尾,右花括号的后面可以跟一个分号(在命名空间的结尾,右花括号的后面可以跟一个分号(在命名空间的结尾,右花括号的后面可以跟一个分号(;)。)。)。)。见例见例见例见例Example_3_1Example_3_1命命名名空空间间的的定定义义和和使使用用2023/1/172023/1/171212第12页,本讲稿共20页命名空间的使用命名空间的使用访问一个命名空间中的成员可以采用下面三种方法:访问一个命名空间中的成员可以采用下面三种方法:访问一个命名空间中的成员可以采用下面三种方法:访问一个命名空间中的成员可以采用下面三种方法:直接访问命名空间的成员(完全限定名)直接访问
17、命名空间的成员(完全限定名)直接访问命名空间的成员(完全限定名)直接访问命名空间的成员(完全限定名):用作用域:用作用域:用作用域:用作用域分解运算符(分解运算符(分解运算符(分解运算符(:)。见例)。见例)。见例)。见例Example_3_2Example_3_2Example_3_2Example_3_2。缺点:输入繁琐。缺点:输入繁琐。缺点:输入繁琐。缺点:输入繁琐。使用声明使用声明使用声明使用声明:用:用:用:用usingusingusingusing声明一次性引用名字。见例声明一次性引用名字。见例声明一次性引用名字。见例声明一次性引用名字。见例Example_3_3Example_3
18、_3Example_3_3Example_3_3。using using 命名空间名命名空间名命名空间名命名空间名:成员名成员名成员名成员名;缺点:缺乏类型信息,不能克服重载问题。缺点:缺乏类型信息,不能克服重载问题。缺点:缺乏类型信息,不能克服重载问题。缺点:缺乏类型信息,不能克服重载问题。l l使用指令使用指令使用指令使用指令:用:用:用:用usingusingusingusing指令把所有名字引入到命名空间中。见指令把所有名字引入到命名空间中。见指令把所有名字引入到命名空间中。见指令把所有名字引入到命名空间中。见例例例例Example_3_4Example_3_4Example_3_4E
19、xample_3_4。using namespace using namespace 命名空间名命名空间名命名空间名命名空间名;缺点:可能会产生命名冲突。缺点:可能会产生命名冲突。缺点:可能会产生命名冲突。缺点:可能会产生命名冲突。命命名名空空间间的的定定义义和和使使用用2023/1/172023/1/171313第13页,本讲稿共20页命名空间的使用小结命名空间的使用小结无名的命名空间允许无限制地使用其成员,并且为其无名的命名空间允许无限制地使用其成员,并且为其无名的命名空间允许无限制地使用其成员,并且为其无名的命名空间允许无限制地使用其成员,并且为其成员提供了成员提供了成员提供了成员提供了
20、内部连接内部连接内部连接内部连接。如果不想由于引入不同命名空间而导致重复定义如果不想由于引入不同命名空间而导致重复定义如果不想由于引入不同命名空间而导致重复定义如果不想由于引入不同命名空间而导致重复定义一个函数时,可以使用一个函数时,可以使用一个函数时,可以使用一个函数时,可以使用usingusingusingusing声明,它不会引起任声明,它不会引起任声明,它不会引起任声明,它不会引起任何二义性和重复。何二义性和重复。何二义性和重复。何二义性和重复。对一个实现文件(对一个实现文件(对一个实现文件(对一个实现文件(.cpp.cpp.cpp.cpp文件):使用一个文件):使用一个文件):使用一
21、个文件):使用一个全局全局全局全局usingusingusingusing指令指令指令指令是一个好方法。因为只有在该文件编译结束时,是一个好方法。因为只有在该文件编译结束时,是一个好方法。因为只有在该文件编译结束时,是一个好方法。因为只有在该文件编译结束时,usingusingusingusing指令才会起作用。指令才会起作用。指令才会起作用。指令才会起作用。对于一个头文件(对于一个头文件(对于一个头文件(对于一个头文件(.h.h.h.h文件):最好使用明确的限定文件):最好使用明确的限定文件):最好使用明确的限定文件):最好使用明确的限定或者被限定在一定范围内的或者被限定在一定范围内的或者被
22、限定在一定范围内的或者被限定在一定范围内的usingusingusingusing指令和指令和指令和指令和usingusingusingusing声明,声明,声明,声明,而不能把一个全局而不能把一个全局而不能把一个全局而不能把一个全局usingusingusingusing指令引入到一个头文件中指令引入到一个头文件中指令引入到一个头文件中指令引入到一个头文件中(因为那将意味着包含这个头文件的任何其他头文(因为那将意味着包含这个头文件的任何其他头文(因为那将意味着包含这个头文件的任何其他头文(因为那将意味着包含这个头文件的任何其他头文件也会打开这个命名空间)。件也会打开这个命名空间)。件也会打开
23、这个命名空间)。件也会打开这个命名空间)。命命名名空空间间的的定定义义和和使使用用2023/1/172023/1/171414第14页,本讲稿共20页命名空间的别名命名空间的别名使用命名空间的完全限定名会觉得太繁琐,命使用命名空间的完全限定名会觉得太繁琐,命使用命名空间的完全限定名会觉得太繁琐,命使用命名空间的完全限定名会觉得太繁琐,命名空间的别名能够解决这个问题。名空间的别名能够解决这个问题。名空间的别名能够解决这个问题。名空间的别名能够解决这个问题。格式:格式:格式:格式:namespace namespace namespace namespace 别名别名别名别名=命名空间名;命名空间
24、名;命名空间名;命名空间名;说明:说明:“别名别名别名别名”可以是任何合法的可以是任何合法的可以是任何合法的可以是任何合法的C+C+C+C+标识符。标识符。标识符。标识符。命名空间的别名为命名空间创建一个简短的命名空间的别名为命名空间创建一个简短的命名空间的别名为命名空间创建一个简短的命名空间的别名为命名空间创建一个简短的名称,以方便命名空间的使用。名称,以方便命名空间的使用。名称,以方便命名空间的使用。名称,以方便命名空间的使用。命命名名空空间间的的别别名名2023/1/172023/1/171515第15页,本讲稿共20页Koenig查找规则查找规则KoenigKoenigKoenigKo
25、enig规则得名于规则得名于规则得名于规则得名于Andrew KoenigAndrew KoenigAndrew KoenigAndrew Koenig(C+C+C+C+语言的先语言的先语言的先语言的先驱之一)。驱之一)。驱之一)。驱之一)。KoenigKoenigKoenigKoenig查找规则查找规则查找规则查找规则:如果命名空间的成员在一个表:如果命名空间的成员在一个表:如果命名空间的成员在一个表:如果命名空间的成员在一个表达式中使用,那么这个命名空间会自动包含在达式中使用,那么这个命名空间会自动包含在达式中使用,那么这个命名空间会自动包含在达式中使用,那么这个命名空间会自动包含在任何使
26、用了这个特定成员的函数调用的查找中。任何使用了这个特定成员的函数调用的查找中。任何使用了这个特定成员的函数调用的查找中。任何使用了这个特定成员的函数调用的查找中。KoenigKoenig查找规则允许自动在命名空间中查找规则允许自动在命名空间中查找函数声明。查找函数声明。Koenig查查找找规规则则2023/1/172023/1/171616第16页,本讲稿共20页 例例例例#include#include#include#include#include#include#include#include using namespace std;using namespace std;using n
27、amespace std;using namespace std;namespace NS namespace NS namespace NS namespace NS struct X string str;struct X string str;struct X string str;struct X string str;void someFunction(X*pX);void someFunction(X*pX);void someFunction(X*pX);void someFunction(X*pX);int main()int main()int main()int main(
28、)NS:X x;NS:X x;NS:X x;NS:X x;someFunction(&x);someFunction(&x);someFunction(&x);someFunction(&x);namespace NS namespace NS namespace NS namespace NS void someFunction(X*pX)void someFunction(X*pX)void someFunction(X*pX)void someFunction(X*pX)pX-str=“Hello”;pX-str=“Hello”;pX-str=“Hello”;pX-str=“Hello”
29、;cout str endl;cout str endl;cout str endl;cout str second)?first:second;首先使用显式的作用域分解运算符,然后使用using声明,最后使用using指令使下面的main()函数成功编译:int main()int answer=greater(3,5);2023/1/172023/1/171919第19页,本讲稿共20页布置作业(续)The End!Thanks!The End!Thanks!2、创建一个带无名的命名空间的头文件,在两个单独的cpp文件中包含这个头文件,验证这个无名的命名空间对于这两个翻译单元来说都是一致的。3、创建一个包含一命名空间的头文件,在命名空间中声明几个函数,再创建另一个头文件,它包含第一个头文件,并在先前的命名空间的基础上再增加几个函数声明。写一个包含第二个头文件的cpp文件,把命名空间用一个短的别名代替,在函数定义里使用作用域运算符调用这些函数。在另一个单独的函数里,通过using指令把命名空间引入到函数中,并证实:这时并不需要作用域运算符调用命名空间里的函数。2023/1/172023/1/172020第20页,本讲稿共20页