7第七讲——名空间和RTTI

合集下载

计算机名人

计算机名人
ห้องสมุดไป่ตู้
安德斯· 海尔斯伯格

安德斯· 海尔斯伯格(Anders Hejlsberg, 1960.12~),丹麦人,Turbo Pascal编 译器的主要作者,Delphi和C#之父,同 时也是· NET创立者。
C++之父
1982年,美国AT&T公司贝尔实验室的Bjarne Stroustrup博士在c语言的基础上引 入并扩充了面向对象的概念,发明了—种新的程序语言。为了表达该语言与c语言 的渊源关系,它被命名为C++。而Bjarne Stroustrup(本贾尼· 斯特劳斯特卢普) 博士被尊称为C++语言之父。后C++语言历经了不断地完善,例如1990年c++语 言引入模板和异常处理的概念,1993年引入运行时类型识别(RTTI)和名字空间 (Name Space)的概念。1997年,c++语言成为美国国家标准(ANSI)。1998年, c++语言又成为了国际标准(ISO)。目前,c++语言已成为使用最广泛的面向对象 程序设计语言之一。
计算机名人
C语言之父
丹尼斯· 里奇,C语言之父,UNIX之父。曾担任朗讯科技公 司贝尔实验室下属的计算机科学研究中心系统软件研究部的主 任一职。1978年与布莱恩· 科尔尼干(Brian W. Kernighan)一 起出版了名著《C程序设计语言(The C Programming Language)》C语言是使用最广泛的语言之一,可以说,C语 言的诞生是现代程序语言革命的起点,是程序设计语言发展史 中的一个里程碑。自C语言出现后,以C语言为根基的C++、 Java和C#等面向对象语言相继诞生,并在各自领域大获成功。 但今天C语言依旧在系统编程、嵌入式编程等领域占据着统治 地位。

RTTI的介绍和使用

RTTI的介绍和使用

RTTI的介绍和使⽤RTTI介绍及使⽤什么是RTTI?RTTI是[运⾏阶段类型识别](Runtime Type Identification) 。

RTTI旨在为程序在运⾏阶段确定对象的类型提供⼀种标准的⽅式。

很多类库已经为其对象提供了实现这种功能的⽅式,但由于c++内部不⽀持,因此各个⼚商的机制通常互不兼容。

RTTI的⽤途为何需要知道类型。

可能希望调⽤类⽅法的正确版本,在这种情况下,只要该函数是类层次结构中所有成员都有的虚函数,则并不真正需要知道对象的类型。

但派⽣对象可能包含不是继承⽽来的⽅法,在这种情况下,只有某些类型的对象可以使⽤该⽅法。

也可能是出于调试的⽬的,想跟踪⽣成的对象的类型。

对于后两种情况,RTTI提供解决⽅案。

RTTI的⼯作原理C++有3个⽀持RTTI的元素。

如果可能的话,dynamic_cast 运算符将使⽤⼀个指向基类的指针来⽣成⼀个指向派⽣类的指针:否则,该运算符将返回0——空指针。

typeid 运算符返回⼀个指出对象的类型的值。

type_info 结构存储了有关特定类型的信息。

警告:RTTI只适⽤于包含虚函数的类1.dynamic_cast 运算符dynamic_cast 不能回答“指针指向的是哪类对象”这样的问题,但能回答“是否可以安全地将对象的地址赋给特定的指针”这样的问题。

#include "stdafx.h"#include <iostream>#include <cstdlib>#include <ctime>using std::cout;class Grand{private:int hold;public:Grand(int h = 0):hold(h){}virtual void Speak() const { cout << "I am a grand class!\n"; }virtual int value() const { return hold; }};class Superb :public Grand{public:Superb(int h = 0) :Grand(h){}void Speak() const { cout << "I am a Superb class!\n"; }virtual void Say() const { cout << "I hold the superb value of " << value() << "!\n"; }};class Magnificent :public Superb{private:char ch;public:Magnificent(int h = 0, char c = 'A') :Superb(h), ch(c) {}void Speak() const { cout << "I am a magnificent class !\n"; }void Say() const { cout << "I hold the character " << ch << " and the integer " << value() << "!\n"; }};Grand *GetOne();Grand *GetOne(){Grand *p = nullptr;switch (std::rand() % 3){case 0:p = new Grand(std::rand() % 100);break;case 1:p = new Superb(std::rand() % 100);break;case 2:p = new Magnificent(std::rand() % 100, 'A' + std::rand() % 26);break;default:break;}return p;}int _tmain(int argc, _TCHAR* argv[]){std::srand(std::time(0));Grand *pg;Superb *ps;for (int i = 0; i < 5; i++){pg = GetOne();pg->Speak();if (ps = dynamic_cast<Superb *>(pg))ps->Say();}return 0;}2.typeid 运算符和type_info类typeid 运算符使得能够确定两个对象是否为同种类型。

Thinking in C

Thinking in C

Thinking in C++1.private与protect关键字的区别。

子类能访问基类的protect成员而不能访问private成员。

2.友元,friend如何声明一个友元。

3.缺省构造函数。

当类声明了一个带参数的构造函数后而没有声明无参数构造函数,编译器还会为它生成一个默认的缺省构造函数吗?分析下例的错误:class A{public:A(int i){cout<<i<<endl;}};void main(){A a;}4.构造函数有没有返回值?析构函数有没有返回值?析构函数可不可以带参数?5.解释一下重载函数重载允许两个或更多个函数使用同一个名字限制条件是它们的参数表必须不同参数类型不同或参数的数目不同。

6.重载函数如何来区分彼此?7.解释缺省参数函数8.下例能编译通过吗?为什么。

重载的缺省参数函数不能与其它函数产生二义。

void s(int i){cout<<i<<endl;}void s(int i, int j=0){cout<<i<<endl;}void main(){s(5);}9.能否用返回值来区分重载函数?10.看下例回答以下问题:a.常量必须初始化,下面的代码又和问题:const int i;i=20;b.常量有没有存储控件,或者只是编译时的符号而已?不一定c.常量一定是在编译时就确定其值的吗?const int i=100;const int j=i+100;long address=(long)&j;//强迫编译器为常量分配存储空间char buf[j+10];void main(){const char c=cin.get();const char c2=c-'a'+'A';cout<<c<<" "<<c2<<endl;}11.看下例回答以下问题:a.能否将一个非常量对象的地址赋给一个常量指针?b.能否将一个常量对象的抵制赋给一个非常量指针?若确要如此,该如何做?void main(){const int i=5;int *j=const_cast<int *>(&i);}const int* x;//常量指针int* const x=&d; //指针常量int const* x; //常量指针const int* const x=&d; //常量指针常量12.函数调用中值传递使用常量定义无甚意义:void f(const int i);但函数返回值的常量定义有特殊作用,看下例:class X{int i;public:void modify(){cout<<"haha"<<endl;}};const X fun(){return X();}void main(){//! fun().modify(); 常量不能为左值,所以下例也不成立://! const X g;//! g.modify();//!!! 常量一定不能为左值吗?看16题}13.常量的典型应用:void u(const int* p);const char* v();14.分析下例说出错误的原因:class X{};X f(){return X();}void g1(X&){}void g2(const X&){}void main(){//! g1(f()); 临时变量都是常量g2(f());}15.如何使用类常量成员,如何初始化?class Y{public:const size;Y();};Y::Y():size(100){}class X{enum{i=100};};//! class X{//! const int i;//! X(){};//! };16.将一个成员函数声明为常量函数有什么作用?a. 编译器保证该函数不得修改成员变量的值b. 允许一个常量对象调用此函数class X{public:void f() const{cout<<"haha..."<<endl;}};void main(){const X cs;cs.f();}17.volatile关键字有什么作用?volatile告诉编译器不要对其做任何自作多情的假设与优化。

c++PRIMER中文版

c++PRIMER中文版

前言C++ Primer的第二版和第三版之间的变化非常大。

最引人注意的是,C++已经被国际标准化,这不但为语言增加了新的特性,比如异常处理、运行时刻类型识别(RTTI)、名字空间、内置布尔数据类型、新的强制转换方式,而且还大量修改并扩展了现有的特性,比如模板、支持面向对象(object-oriented)和基于对象(object-based)程序设计所需要的类(class)机制、嵌套类型、以及重载函数的解析机制。

也许更重要的是,一个覆盖面非常广阔的库现在成了标准C++的一部分,其中包括以前的标准模板库或STL。

新的string类型、一组顺序和关联容器类型——比如vector、list、map和set——以及在这些类型上进行操作的一组可扩展的泛型算法(generic algorithms),都是这个新标准库的特性。

本书不但包括了许多新的资料,而且还涵盖了怎样在C++中进行程序设计的新的思考方法。

简而言之,实际上,不但C++已经被重新创造,它的C++ Primer,第三版,也有了很大的变化。

在此第三版中,不但对语言的处理方式发生了根本的变化,而且作者本身也发生了变化:首先,我们的人数已经加倍。

而且,我们的写作过程也已经被国际化了(尽管我们还牢牢扎根于北美大陆):Stan是美国人,Josée是加拿大人。

最后,这个双作者关系也反映了C++团体的两类主要活动:Stan现在正在华特迪思尼动画公司(Walt Disney Feature Animation)致力于以C++为基础的3D计算机图形和动画应用,而Josée正专心于C++的定义与实现,同时她也是C++标准的核心语言小组的主席,以及IBM加拿大实验室的C++编译器组的成员。

Stan是Bell实验室中与Bjarne Stroustrup(C++的发明人)一起工作的早期成员之一,从1984年开始一直从事C++方面的工作。

Stan曾经致力于cfront的各种实现,从1986年的版本1.1到版本3.0,并领导了2.1和3.0版本的开发组。

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导由上图得到每种特性的运行时开销如下:可见,关于老天“饿时掉馅饼、睡时掉老婆”等美好传说纯属谣言。

但凡人工制品必不完美,总有设计上的取舍,有其适应的场合也有其不适用的地方。

C++中的每个特性,都是从程序员平时的生产生活中逐渐精化而来的。

在不正确的场合使用它们必然会引起逻辑、行为和性能上的问题。

对于上述特性,应该只在必要、合理的前提下才使用。

"dynamic_cast" 用于在类层次结构中漫游,对指针或引用进行自由的向上、向下或交叉强制。

"typeid" 则用于获取一个对象或引用的确切类型,与 "dynamic_cast" 不同,将 "typeid" 作用于指针通常是一个错误,要得到一个指针指向之对象的type_info,应当先将其解引用(例如:"typeid(*p);")。

一般地讲,能用虚函数解决的问题就不要用"dynamic_cast",能够用 "dynamic_cast" 解决的就不要用 "typeid"。

比如:voidrotate(IN const CShape& iS){if (typeid(iS) == typeid(CCircle)){// ...}else if (typeid(iS) == typeid(CTriangle)){// ...}else if (typeid(iS) == typeid(CSqucre)){// ...}// ...}以上代码用 "dynamic_cast" 写会稍好一点,当然最好的方式还是在CShape里定义名为 "rotate" 的虚函数。

虚函数是C++众多运行时多态特性中开销最小,也最常用的机制。

ASP.NET常见面试题及答案(130题)

ASP.NET常见面试题及答案(130题)

常见⾯试题及答案(130题)1. 简述 private、 protected、 public、 internal 修饰符的访问权限。

答 . private : 私有成员, 在类的内部才可以访问。

protected : 保护成员,该类内部和继承类中可以访问。

public : 公共成员,完全公开,没有访问限制。

internal: 在同⼀命名空间内可以访问。

2 .列举 页⾯之间传递值的⼏种⽅式。

答. 1.使⽤QueryString, 如....?id=1; response. Redirect()....2 .使⽤Session变量3.使⽤Server.Transfer4.C#中的委托是什么?事件是不是⼀种委托?答:委托可以把⼀个⽅法作为参数代⼊另⼀个⽅法。

委托可以理解为指向⼀个函数的引⽤。

是,是⼀种特殊的委托5.override与重载的区别答:重载是⽅法的名称相同。

参数或参数类型不同,进⾏多次重载以适应不同的需要Override 是进⾏基类中函数的重写。

为了适应需要。

6.如果在⼀个B/S结构的系统中需要传递变量值,但是⼜不能使⽤Session、Cookie、Application,您有⼏种⽅法进⾏处理?答: this.Server.TransferResponse. Redirect()---QueryString9.描述⼀下C#中索引器的实现过程,是否只能根据数字进⾏索引?答:不是。

可以⽤任意类型。

11.⽤.net做B/S结构的系统,您是⽤⼏层结构来开发,每⼀层之间的关系以及为什么要这样分层?答:⼀般为3层:数据访问层,业务层,表⽰层。

数据访问层对数据库进⾏增删查改。

业务层⼀般分为⼆层,业务表观层实现与表⽰层的沟通,业务规则层实现⽤户密码的安全等。

表⽰层为了与⽤户交互例如⽤户添加表单。

优点:分⼯明确,条理清晰,易于调试,⽽且具有可扩展性。

缺点:增加成本。

13.什么叫应⽤程序域?答:应⽤程序域可以理解为⼀种轻量级进程。

c++ 第2章-2.4指针与名字空间

c++  第2章-2.4指针与名字空间

指针型变量的定义
“先定义后使用”
一般格式:
类型描述符* 指针变量名表; 例: int* ptr; float* array;
char *s1,*s2;
例:int *p;
*p=3;
随机内容 1000H 随机内容 随机内容
p 编译可能通过,但危险!!!
定义一个指针后,必须先给它赋值后才能引用,否则将
const修饰符的用法 格式1:普通常量 const 类型 常量名 = 值;
const double PI = 3.1415;
格式2:引用 const 类型 &引用名 = 变量名;
说明:不能通过常引用修改所引用的对象。
int i = 0; const int &refi = i; i++; // refi++; //
OK
Error!
const修饰符的用法
格式3: 修饰指针变量指向的变量,放在类型前面
const 类型 *指针变量;
int a = 6, b = 7; const int *p = &a //表示不能通过p改变p指向的内存的内容 *p=19
//错误
//正确
a = 19;
p = &b;
//正确
array
//*(a+i) = rand();
{ int array[3]; init( array, 3 ); return 0; }
4.3
void和const类型的指针
void指针
void在作为函数类型和参数类型时为空类型,表示没有返 回值或参数。 void修饰指针时称为“无类型指针”,表示该指针可以指 向任意类型的变量。 虽然void指针可以指向任意类型的数据,但是在使用void

第六讲 空间数据索引技术与空间查询语言(2)ppt课件

第六讲 空间数据索引技术与空间查询语言(2)ppt课件
④ 查询:圣劳伦斯河能为方圆300公里以内的城市供 水,列出能从该河获得供水的城市。
⑤查询:求出河流在流经的各国境内的长度 ⑥查询:按其邻国数目的多少列出所有国家。
四、空间查询处理
过滤筛选步骤(Filter): 细化步骤(Refine): 用一个不精确的大致范围来进行查询,产生
一个满足条件的较小候选集合。对候选集合 中的对象进行精确的筛选,产生最终的查询 结果。
点四叉树的每个结点存储了一个空间点的信 息及孩子结点的指针。
(0,100) D (30,90)
B (10,75)
(100,100) N WN E
A
SWSE
F(80,70)
F BC E
A (45,45)
C (25,15) E(70,20)
D
(0,0)
(100,0)
(a)平面图
(b)结构图
图5-22 一颗二维的点四叉树结构
本讲重点内容
➢ 空间索引的定义 ➢ 各种空间索引方法 ➢ 主要的空间操作算子 ➢ 空间查询的处理步骤
此课件下载可自行编辑修改,此课件供参考! 部分内容来源于网络,如有侵权请与我联系删除!感谢你的观看!
Disjoint(anotherGeometry ) Intersects(anotherGeometry ) Touches(anotherGeometry ) 空间 Crosses(anotherGeometry) 关系 Within(anotherGeometry) 运算
Contains(anotherGeometry)
PR四叉树叶子结点可能不在树的同一层次;叶子结 点的黑结点或空结点分别表示数据空间某一位置空 间点的存在与否。
H
G
B F I
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

void main () { G(); using namespace A; F(); B::F(); B::C::F(); G():from global namespace A::G(); F():from namespace A } F():from namespace B
F():from namespace C
include 与 using namespace 的区别和联系: 前者是将某文件搬到本地来,搬来了未必好用,是否 能用全在后者。 using ... 只是告诉编译器,扫描源代码时,凡遇到非 本作用域的标识符该到哪去找。
#include <iostream.h> namspace A { void F () { cout<<“F():from namespace A”<<endl; } void G () { cout<<“G():from namespace A”<<endl; } namspace B { void F () { cout<<“F():from namespace B”<<endl; } namspace C { void F () { cout<<“F():from namespace C”<<endl; } } } } void G () { cout<<“G():from global namespace”<<endl; }

使用名空间的方法:
1. 将使用的标识符前加名空间名——凡用就加: NS:: File obj; NS:: Fun (); 这属于“单个一次性开放”,且每次使用都得加。 尽管繁琐,但小巧灵活。此法用于使用的名空间 标识符个数、次数较少时。 2. 用using声明,一劳永逸地指定,免去了每次必须指 定的繁琐。属于“单个一劳永逸开放”,: 例如,经过以下声明: using NS::File; 在当前作用域中就可以不再加标识地直接引用File。 此法用于使用的名空间标识符次数频繁时。
G():from namespace A
VC6.0的名空间不成熟
1. 在VC6.0中,名空间与友元冲突,编译器会报错。 只好舍弃其中的一个。 2. 名空间还会与模板冲突。
这只是VC不成熟的表现,到后来的VC7.0、8.0 就完全解决了。但这时你只能忍疼割爱,放 弃其中的一个。
名空间设计规范
首先,根据问题,分析分解产生“函数调用关 系图”。该图应标明三个层次的模块划分(程 序级、文件级、函数级)。注意要按调用关系 而非依赖关系划分。 按规则转换为“文件组模块”。 按模块从宏到微的次序,将个模块的输出归纳 于各头文件中,并以各名空间命名。 再以模块(最外层)为单位,归纳为上一级名空 间,产生更抽象的头文件。 最后分别实现这些资源。
// file3.h namespace f3 { void h1(); }
// file4.h namespace f4 { void n1(); void n2(); }
k4
k2
文件5
k1 h1 k1
k5
k3
m2
文件6
m1 m1 m1
m3
模块3
// module1.h namespace m1 { #include “file1.h” } //using namespace f1; // module2.h namespace m2 { #include “file2.h” #include “file3.h” } //using namespace f2; //using namespace f3;
namspace B { class File; void Fun (); namspace C //名空间可以嵌套。 { class File; void Fun (); } }
匿名空间
“匿名空间”:设定一个无名的命名空间,将标识符 集合其内,由于无名,本文件的域外可以无限制地 使用该空间的标识符,省却了定义时的static,使用 时也节省了空间名前缀。但别的文件不可使用。因 此匿名空间的作用相当于C时代的静态全局变量 。 如: namspace { class File; void Fun (); } 匿名空间也可以跨文件追加。 一个编译单元只可有一个匿名空间。

然后,在源程序开发时,就可以将这三个模块 文件作为资源使用。当然,要对各头文件中所 涉及的函数予以实现。

名空间尽管发源于模块的划分和隔离,服务于 模块设计的开发模式,但从中受益的不仅是模 块,还有数据的使用。当然数据要求更细致的 服务,名空间就显粗糙了些,更精细的是类。

四个强制转换运算符 RTTI的概念 RTTI的两种使用方法 合理使用RTTI
新增的四个强制类型转换符
“强制”的含义: 在告诉编译器: “我知道你不愿意这样做,可是你必须做。尽管 执行吧,后果由我负责!”
const_cast
对象自身.
static_cast
除去对象的常属性。转换的是表达式而非 形式:const_cast < type > ( object )
欲引进多个名空间时,可在当前区域内使用如下语句: using namespace 空间名1; using namespace 空间名2; 当前区域是指using指令所在的位 臵,如函数内、文件内等等 此时在两个名空间有同名标识符时会产生二义性。区分 的方法同上。

主函数不可放入任何名空间中。

ቤተ መጻሕፍቲ ባይዱ
在新的C++标准程序库中,系统所用的标识符都声明 在命名空间std中,而未使用名空间的程序,都使用 带.h的头文件,则意味着其标识符都是全局的。
1规则的示例:
在名字空间之外使用时要时刻带空间名: namespace Parser { double prim( bool);
double term( bool);
} double Parser::prim( bool get) {} double Parser::term( bool get) {}
3. “全面开放,一劳永逸”
用指示符using:
using namespace std;语句后,名空间std中的所有 标识符都在本作用域中开放,可直接使用。此法将引 起标识符的“全面冲突”。 此法用于使用的名空间标识符个数、次数都很多时。 此法将因别的名空间的引进而产生“名冲突”。编 译器的仲裁准则是“外来服从本层”。它的在外层, 你的在内层,内层屏蔽外层。被屏蔽的同名者可用空 间名::标识符 来区分。 用2方法打开时可能发生的“个别冲突”,也用此 法解决。
C/C++的命名原则

C/C++/C#/Java等语言都遵循的命名原则:在同一 作用域内,不得命名相同名称的同种类标识符,否 则视为“名冲突”语法错误。 “命名冲突”:在不同文件模块中使用了相同的名 字来表示不同的事物,当这些模块一旦由头文件导 入凑到了一起,则会引起名称的混乱。 名空间如同磁盘的子目录,标识符如同各子目录下 的文件。名空间如同子目录一样可以嵌套。使用名 空间如同使用文件时要加路径,不过那是用于文件 的,名空间不能用,名空间有特定的使用方式。
C++语言程序设计
命名空间和RTTI
本章主要内容

命名空间 RTTI的概念 RTTI的两种使用方法 合理使用RTTI
在无“命名空间“的年代
记得在五六十年代,火车站的候车室(还有 候船厅)里都有块“旅客留言板”。人们在上 面留下自己的纸条。“小李,我已乘xx次列车 走了。”、“老王,我已抵连,现住在xx旅 馆。” ... 开始,旅客较少时很方便。但随着 旅客的增多,由于简称、同名等造成的误解, 带来的不是方便,而是混乱。 可见公共资源的是不可滥用的,必须加以限 制。
使用using namespace std;语句的同时要求标准库 的头文件都不得使用扩展名.h ,但用户自定义的头 文件可以带.h 。

//用using namespace std;打开标准库的标识符 #include <set> #include <iostream> void main() { using namespace std; //一劳永逸地打开 using std::set<int>::iterator; // 永久打开了iterator int a[100] = {10}; set<int> iSet(a,a+99); iterator it = iSet.find(25); cout<<" "<<*it<<endl; }
命名空间(namespace)
“命名空间”:为语言再设定一个命名的作用域 (named scope)——又加了一层隔离带,将所用 的标识符集合其内,域外使用时便多了一层名称来 标明归属。“名空间”在UML 中统称为“包”。 声明一个命名空间NS: namspace NS { class File; void Fun (); ... // 所有空间成员的声明必须写在名空间内 }
namespace U{ void f(); void s(); } namespace V{ void f(); //可以有多个f,它们是重载关系 void s(); 将引进重载的所有的f() } void func() { using namespace U; using V::f; // 注意,只写f,不写参数和返回类型 f(); // 必然是V空间的f() U::f(); // 这才是U空间的f() }

名空间的性质

“名空间”是跨越文件的。它不是简单的包含了文件, 而是更灵活的超越了文件。是个逻辑概念,就如同活动 在校内外的学生依然从属于某系某班级一样。
相关文档
最新文档