2007年01月05日

 在一个含有基类和派生类的程序中,往往各个类中相应的成员函数具有相同的函数名、返回类型和参数表,但函数体不同(语义不同)。在每个类中都有定义实现相应功能的成员函数。

    当一个派生类的对象的地址赋给一个基类的指针后,基类指针只能访问所属的成员函数,不能访问该派生类对象中与基类成员函数相同的成员函数。但在实际应用中,需要把一个基类或派生类的对象的地址赋给一个基类的指针后,基类指针能够访问基类或派生类中与基类成员函数相同的成员函数。解决问题的方法是使用虚函数,把基类和派生类中相同的函数同时定义为虚函数

虚函数的定义方法是在成员函数前加关键字 virtual 

    当基类和派生类中相同的函数定义为一组虚函数后,通过基类指针可以调用任一类中虚函数的执行。

    这种通过调用基类的虚函数就能够调用一组虚函数中任一个虚函数的执行的技术称为多态性

    下面是一个使用虚函数的例子:

#include <iostream.h>

class AA{

  int x;

public:

    AA(int xx=0):x(xx){ }

    virtual void print() { cout <<"x="<<x<<endl;}

};

class BB :public AA{

  int y;

public:

    BB(int xx=0,int yy=0):AA(xx){y=yy; }

    virtual void print() {

    AA:print();

    cout <<"y="<<y<<endl;

    }

};

 

class CC :public AA{

  int z;

public:

    CC(int xx=0,int zz=0):AA(xx){ z=zz; }

    virtual void print() {

    AA:print();

    cout <<"z="<<z<<endl;

    }

};

 

void main()

{

  AA a(2);

  BB b(3,4);

  CC c(5,6);

AA *p[3]={ &a,&b,&c };

  for (int i=0;i<3;i++)

        p[i]->print();

}     

运行结果:

x=2

x=3

y=4

x=5

z=6 

又如,在上章中计算球、圆柱和圆锥的表面积和体积的例子中,可以把圆类中的计算圆、球、圆柱和圆锥的计算面积和体积的成员函数定义成虚函数。

//Circle.h>

#include <math.h>

#define PI 3.14159

class Circle { //圆类

protected:

    double r; //半径

public:

    Circle(double radius=0):r(radius){ }

    virtual double area(){return PI*r*r;} //定义计算物体面积的虚函数

    virtual double volume(){return 0;}; //定义计算物体体积的虚函数

};

 

class Sphere: public Circle { //球体类

public:

    Sphere(double radius=0):Circle(radius){ }

    virtual double area() { return 4*PI*r*r; } //计算球的表面积的虚函数

    virtualdouble volume(){ return 4*PI*pow(r,3)/3;} //计算球的体积的虚函数

};

 

class Cylinder: public Circle { //圆柱类

private:

    double h; //高度

public:

    Cylinder(double radius=0,double height=0):Circle(radius){

        h=height;

    }

    virtual double area(){ return 2*PI*r*(r+h);} //计算圆柱表面积的虚函数

    virtual double volume() { return PI*r*r*h; } //计算圆柱体积的虚函数

};

       

class Cone: public Circle { //圆锥类

private:

    double h; //高度

public:

    Cone(double radius=0,double height=0):Circle(radius){

        h=height;

    }

    virtual double area(){ //计算圆锥的表面积的虚函数

        double he=sqrt(h*h+r*r);

        return *PI*r*(r+he);

}

    virtual double volume(){ return PI*r*r*h/3;} //计算圆锥的体积的虚函数

};

 

//main.cpp

#include <iostream.h>       

void main()

{

Sphere r1(2);

Cylinder r2(2,3);

Cone r3(2,3);

Circle *a[3]={ &r1,&r2,&r3 };

for (int i=0;i<3;i++)

    cout <<a[i]->area()<<" "<<a[i]->volume()<<endl;

}

运行结果:

50.2655 33.5103

62.8319 37.6991

35.2207 12.5664

 

main.cpp还可写成:

#include <iostream.h>

#include "circle.h"

void printarea(Circle & c1) {

cout<<c1.area()<<endl;

}

void printvolume(Circle &c2)

{

cout<<c2.volume()<<endl;

}

void main()

{

Sphere r1(2);

Cylinder r2(2,3);

Cone r3(2,3);

printarea(r1);

printvolume(r1);

printarea(r2);

printvolume(r2);

printarea(r3);

printvolume(r3);

}

运行结果:

50.2655

33.5103

62.8319

37.6991

35.2207

12.5664

2007年01月04日
2006年07月30日

    中断技术和通道技术的引入,提供了CPU,通道和I/O设备之间的并行操作的可能性,但由于计算机外设的发展会产生通道不足而产生的"瓶颈"现象,使并行程度受到限制,因此引入了缓冲技术.
目的:
1,改善CPU和I/O设备之间速度不匹配的情况;
2,可以减少I/O设备对CPU的中断次数及放宽对CPU的中断响应时间要求;

   

    数据在网络上是以很小的称为帧(Frame)的单位传输的,帧由几部分组成,不同的部分执行不同的功能。帧通过特定的称为网络驱动程序的软件进行成型,然后通过网卡发送到网线上,通过网线到达它们的目的机器,在目的机器的一端执行相反的过程。接收端机器的以太网卡捕获到这些帧,并告诉操作系统帧已到达,然后对其进行存储。
    帧是专业术语Frame的翻译。
   内核或微核提供核外调用的过程或函数称为原语(primitive)。原语是一段用机器指令编写的完成特定功能的程序,在执行过程中不允许中断。换一种说法是指那些最初编定的、用户不可改变的完成核心功能的程序。

    在异步传输中,信息以字符为单位进行传输 。
异步传输的优点就是收、发双方不需要严格的位同步,所谓“异步”是指字符与字符之间的异步,字符内部仍为同步。
    在同步传输中,不仅字符内部为同步,字符与字符之间也要保持同步。同步传输的特点是可获得较高的传输速度,但实现起来较复杂。

  简单的讲,数字信号是指用0.1.2……的数字来表达的信号,在信号的大小和时间上都是离散的,即随时间的变化是阶跃的。在电子电路中,采用电平的高低来表示数字1.0,也可以用频率或周期的高低表示1.0。现在的数字系统一般采用二进制数表示,即每一位数只有0和1两个数码,称为二进制数字系统,在电子电路中用晶体管的截止和饱和导通时的集电极电压就可以实现。
  自然界中存在的物理量的大小和时间都是连续的,如果转换成电信号,其大小是随时间变化的,称为模拟信号。
虽然一位二进制数可表示的信息量太小,但只要增加位数就可以大大提高信息量和表达的精度。
   采用信号变换技术就可以实现模拟与数字信号的转换,即A/D和D/A转换技术。电视机中的遥控器发射的编码脉冲就是典型的数字信号,每一个按键按下去产生的脉冲是由一组在规定时间里有多少脉冲来决定。
直接用模拟信号进行广播的系统就叫模拟广播,把模拟信号进行A/D转换之后进行广播就叫数字广播。数字信号由于抗干扰能力强,又便于用计算机技术处理,因此得到广泛的发展。

2006年07月29日

    进程的一个比较正式的定义是∶在自身的虚拟地址空间运行的一个单独的程序。进程与程序是有区别的,进程不是程序,虽然它由程序产生。程序只是一个静态的指令集合,不占系统的运行资源;而进程是一个随时都可能发生变化的、动态的、使用系统运行资源的程序。而且一个程序 可以启动多个进程。

 进程和作业的概念也有区别。一个正在执行的进程称为一个作业,而且作业可以包含一个或多个进程,尤其是当使用了管道和重定向命令。

   "exit()"与"_exit()"的基本区别在于前一个调用实施与调用库里用户状态结构 (user-mode constructs)有关的清除工作(clean-up),而且调用用户自定义的清除程序 (译者注:自定义清除程序由atexit函数定义,可定义多次,并以倒序执行),相对应,后一个函数只为进程实施内核清除工作。

    _exit终止调用进程,但不关闭文件,不清除输出缓存,也不调用出口函数。 exit函数将终止调用进程。在退出程序之前,所有文件关闭,缓冲输出内容将刷新定义,并调用所有已刷新的“出口函数”(由atexit定义)。

2006年07月24日

     文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。第一个打开的文件是0,第二个是1,依此类推。Unix 操作系统通常给每个进程能打开的文件数量强加一个限制。更甚的是,unix 通常有一个系统级的限制。

     句柄就是用来区分各种内存对象的唯一标识符号,是个32位整数。 有些是整个系统唯一(如窗口句柄),有些是当前进程或线程中唯一 (如线程句柄,全局的有另一个标识符)。

计算机的外部设备很多,同种类型的设备又有不同厂家、不同型号的产品。这些产品总会有些细微的差别。这就给应用程序的编写带来很大的困难,因为一个应用程序不可能顾及到所有硬件的兼容性。为此,操作系统将具体的硬件设备同整个系统隔离开来,对硬件的具体操作、与硬件有关的兼容性问题等统统 由设备驱动程序来解决,同时操作系统向应用程序提供统一的操纵设备的方法,应用程序只需要按套路调用操作系统提供的功能即可,无须关心实际的设备是什么,这就是与设备无关性.这样,每增添或改动一个系统上的硬件,只需要安装相应的驱动程序即可。