您的位置:首页 > 编程语言 > C语言/C++

C++学习日记day06

2012-03-22 21:09 232 查看
第六课

1.动态绑定的底层实现——虚函数表

class A {...};

class B : public A {};

A* pa = new B;

当编译器编译如下语句时

pa -> foo ();

它并不知道pa所指向对象的真实身份,编译器所能做的就是用一段代码替换上面的函数调用语句,这段代码将依次执行下列操作:

1) 首先弄清指针pa所指向对象的真实身份;

2) 然后通过这个对象的虚函数表指针_vftbl访问其虚函数表,并找到与foo()标识符相对应的虚函数入口地址;

3) 根据虚函数的入口地址,调用该函数。

实现多态的必要条件:

1) 虚函数;

2) 通过指针或者引用调用。

class A {

public:

void foo (void) {

bar (); // this -> bar (),this是一个指向B对象的A*

}

virtual void bar (void) {

}

};

class B : public A {

public:

void bar (void) {}

};

int main (void) {

B b;

b.foo ();

}

构造函数、析构函数、运算符函数、静态成员函数,哪些不可以是虚函数?为什么?

构造函数和静态成员函数不能被定义为虚函数。

2.类型信息和类型转换

1)类型信息

int n;

typeid (int)

typeid (n)

返回typeinfo对象,在该对象上调用name()成员函数,获取类型名。

typeinfo对象支持==判断。

只有在具有多态关系的父子类之间,才能通过typeid正确地判断一个指针实际指向的对象类型。

2)类型转换

dynamic_cast:一般用在具有多态继承关系的父子类之间。

static_cast:一般用在需要检查类型相关性的场合。

reinterpret_cast:一般用在自己对所要做的事情十分清楚的场合。

练习:实现一个动物园,动物园里面关着三种动物,小鸟、小鱼和狮子,所有的动物都有编号,每种动物又有自己的特定,小鸟有最高飞行高度,小鱼有最远游行距离,狮子有最快奔跑速度。每种动物类提供如下接口:

Like()返回该动物喜欢吃什么。

Eat()进食。每种动物在进食之前,要自我介绍一下。

动物园提供接口:

Raise()加入一种动物。

Feed()喂养所有的动物。

动物园解体的时候所有的动物获得自由,高呼“自由万岁”,每种表达一下自己愉快的心情。

Animal:编号,

/ | \

Bird Fish Lion

Zoo 最多养10只动物。

3.异常

异常捕获:

try {

可能引发异常的语句;

}

catch (异常类型1 ex) {

异常处理语句;

}

catch (异常类型2 ex) {

异常处理语句;

}

...

catch (...) {

异常处理语句;

}

异常抛出:

throw 异常对象;

异常的基本用法:

1.抛出简单类型变量,用异常变量的值区分不同的异常

2.抛出类类型异常对象,通过异常类型区分不同的异常

3.从标准异常继承

4.继续抛出异常

5.异常说明

返回类型 函数名 (形参表) throw (异常类型1, 异常类型2, ...) {...}

构造函数中的异常:构造函数可以抛出异常,而且在某些情况下必须抛出异常。如果构造函数抛出异常,所构造的对象将被不完整构造,而一个不完整构造的对象的析构函数是不会被调用的。如果在抛出异常之前动态分配的对象,应该在throw之前将其释放。或者通过智能指针保证所有动态分配的对象都能在抛出异常之后被自动析构。

析构函数中的异常:最好不要在析构函数中抛出异常,这样做会导致进程进入不稳定状态。尽可能地捕获析构函数中的函数调用所引发的异常。

A::~A (void) {

try {

全部代码;

}

catch (...) {

}

}

4.I/O流

1) 文本文件I/O

A. 格式化I/O

B. 文件位置

C. 非格式化I/O

2) 二进制I/O
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: