博文

<C++语言命令详解>第九章:虚函数及其性质(2005-08-27 09:27:00)

摘要:    面向对象的程序可以说是一系列对象实体通过互相发送消息的方法进行相互通讯,同时这些消息本身应该具有一定的独立性,我们可以自由地发出消息而无须知道接收方是谁。     虚函数的内涵同上面的一样。虚函数的调用不必在意是通过哪种类型的对象向这些虚函数发出调用请求的。虚函数表示函数是以间接的方式被调用而不是由一个固定的函数入口地址来调用。定义方式:Virtual return_type name (urguments)(virtual void name(void)=0 表示该函数是纯虚函数,它与一般虚函数没什么区别,只是它里面没实现语句);它所有的派生类都默认地保持virtual类型,它将被延迟绑定,即知道程序运行时才决定该函数的入口地址。(内插函数不能加virtual而变成虚函数)     虚函数的作用是为了配合通过基类指针访问某一对象的操作。如果在派生类里没有对某一函数进行重载,也就不必把此函数声明成虚函数。同样代码的虚函数比普通函数更占内存。     具有纯虚函数的类定义为抽象类,它在使用时有个致命的限制:它不能被直接创建对象,但可以声明一个指向它的指针。......

阅读全文(2889) | 评论:0

<C++语言命令详解>第八章:继承C++的优越性(2005-08-27 08:45:00)

摘要:继承的定义方式CLASS Derived_class : PUBLIC Base_class { declarations };,public是对基类的访问标志符,但也可以是protected或private。     继承时,必须先包含基类的声明文件。     在派生类里,可以重载基类里的函数,如果要用基类里的函数,必须在前加作用域符,否则系统认为是在用派生类中重载的函数。     一般来将,当编译器读到一个函数名时,它按照下步骤寻找函数来源:1、在定义成员函数时出现的函数名,编译器首先检查该名称是否在类里进行了声明,如果发现了此声明,就使用这个声明过的函数;2、如果编译器没有在类里找到函数的生命,下一步它将在基类里寻找此函数的声明(依级别进行);3、如果函数名称没在类的派生层次里声明过,编译器将检查它是不是全局函数。     注:如果一个函数在派生类里被重载,这个函数通常被定义为虚函数。     protected访问权限的成员,可以在类的作用域和它的派生类里被读写,但此范围之外受到保护。     基类构造函数:C++总试图调用基类的构造函数来创建新的对象,而如果没指定基类构造函数,编译器就会调用派生类的缺省构造函数。所以,在调用派生类的缺省构造函数之前,派生类里继承基类的成员已经被初始化了一次。而且,如果基类的成员是私有的,则派生类根本无法进行初始化工作,因为它不能读写继承而来的私有成员。解决方法就是在派生类的构造函数里指定合适的基类构造函数,语法格式为:class::class( arglist1 ):base_class( arglist2 ) { statements } ,(arglist2从arglist1里选择合适的参数)这样就只要执行一次初始化。     如果不进行类型转换,C++是不允许把一种类型的指针赋值给另外一种类型的指针的,但允许程序员用基类类型的指针指向派生对象(单向)。此时,如果基类里有个函数被派生类重载,则编译器假设调用的是基类的函数而非派生类的函数。解决方......

阅读全文(3785) | 评论:0

<C++语言命令详解>第七章:类的运算(操作符重载)(2005-08-27 07:22:00)

摘要:    除了非常少的几种特例外,用户几乎可以自定义所有的C++操作符。在每一个操作符出现的表达式里,都有一个相应的函数调用来计算该表达式的值,而这一函数又是根据操作符和操作数的类型来决定的。     对于某一操作符@,对应的操作符函数名称为: operator@。     函数所进行的操作是双操作数的(binary)还是单操作数的(unary)?     如果所进行的操作是双操作数的,是否支持操作对象出现在操作符任何一侧的情况?如果支持,则需要使用友元函数(friend)。     在编写双操作数操作符函数时,经常要使用关键字friend,这种情况下,一个双操作符只能用在两个操作数之间。如果不使用friend关键字,则只能在操作符的左侧使用类对象。     一般来说,类的全局函数不能访问该类的私有成员,但是friend的全局函数可以访问(操作符函数作为类的成员的情况下)。如果操作符函数在类之外定义,则不需要某个类才能调用,任何类都可调用。     赋值号(=)是一个特殊的操作符,如果没对它编写程序,编译器将提供一个隐含函数来实现它的功能。C++里有个普遍的规则,同种类型对象之间的赋值总是被支持的,它就是成员到成员的直接赋值。     在成员函数中,关键字this是一个指向当前对象的指针(这里所说的当前对象,是指主调函数通过该对象调用某一函数)。每次用户调用一个成员函数时,C++都把一个隐含的this指针传递给函数的参数。一个操作符函数是属于哪个操作数对象的,this指针就指向该对象,称当前对象。     引用操作(&)允许用户在对象之间传递数据(共享)而不必创建多余的拷贝,它也不必使用指针表达式。     类型转换函数。对于任何特定的类,类型转换函数处理向外的转换(转变为另外一个类型),而构造函数(本身具有类型转换功能)执行向内的转换(从其它类型转变为此类型)。类型......

阅读全文(3043) | 评论:0

<C++语言命令详解>第六章:构造函数(2005-08-22 03:40:00)

摘要:    可以为同一个类编写许多不同的构造函数(可重载),在每个构造函数中有不同的变量或变量类型。     默认构造函数,每个函数都应该有一个默认的构造函数,它没有任何参数。系统提供的默认构造函数就简单地把所有成员变量初始化为0(但没认为编写默认构造函数时,系统会简单提供一个隐藏的默认构造函数)。     复制构造函数,当函数中对象作为值传递或函数返回一个对象时,系统自动调用复制构造函数。如果没认为地编写复制构造函数时,系统会简单地产生一个隐藏的复制构造函数,它完成成员到成员的复制(不共享数据,除了指针使用处外)。     一般我们使用引用来定义复制构造函数,它产生一个对象的别名,所以两个对象共享同一数据块。但这样容易毁坏数据。如CStr::CStr(CStr &CStr),注意其中每个CStr的含义。     当使用Const关键字限制时,就可以避免错误的发生。CStr::CStr( Const CStr &CStr),这样复制构造函数就不能改变原始数据的任何值。     复制构造函数:CStr name2= name1 ; 与 CStr name2(name1);是等价的。其中第一句并不是name2调用默认初始化函数,然后再将name1的值赋给它,而是与第二句一样,调用复制构造函数。......

阅读全文(2998) | 评论:0

<C++语言命令详解>第五章:类(2005-08-22 03:00:00)

摘要:    在用class声明类时,缺省为private。     在类的成员函数定义时使用"::",而在调用其成员函数时使用"."。     类(class)、结构(struct、typedef)、联合(union),后两者可以看做类的特殊情况。     对象有自己的数据拷贝空间,但是其代码还是共享类的函数代码。     C++支持new和delete关键字动态创建对象,new返回一个指针。        格式:Classname * Pointname;              Pointname = new Classname;     尽管malloc和free也可以动态分配内存,但是new和delete能自动调用构造函数和析构函数。   在创建对象指针时,最好初始化,否则容易造成内存泄漏。     构造函数是类的本名,析构函数是在前面加"~";它们有个特点就是没返回类型(连void也没有),并且函数的参数列表可以什么都不写,而不使用void。   类的封装性迫使外部在使用内部函数时必须通过公共函数的调用,降低了程序运行的效率,内联函数解决了这个问题。在类(函数)的声明中定义的函数是被自动内联的,而且C++也支持inline命令定义内联函数,这样外部函数就可以直接使用内部函数了,大大提高了效率。     在C++中,类与结构唯一的区别是:结构中默认的成员是公共的,而类中默认是私有的。结构中也可以有成员数据和成员函数。     除了使用多重继承时,每个对象都属于单一的类。......

阅读全文(3605) | 评论:0

<C++语言命令详解>第四章:输入、输出和C++(2005-08-22 01:01:00)

摘要:C++把流对象cin和cout作为输入输出的接收和发送终端。     并不是所有的输入输出都和键盘和屏幕有关。     流是单向的,而且它基本上是无穷尽的。     文件经常被看作流。     流的定义:它是一种使用环境,在这种环境下,“对下一个字节进行处理”是可行的,也是有意义的。     流操作符是左移右移操作符的重载,它在istream和ostream中被重新定义。     cout<<item等价于cout本身,所以cout<<item1<<item2<<item3等价于cout<<item1,cout<<item2,cout<<3;同样的道理,cin>>item等价于cin本身,cin>>item1>>item2>>item3等价于cin>>item1,cin>>item2,cin>>item3。因为cout<<item或cin>>item都会传送字符串或数据到cout或cin本身。     cin和cout每种数据类型都由操作符来决定,而且每种数据类型都有合理的默认表达式。     C++的三种输入输出方式:流操作<<和>>,printf和scanf函数,puts和gets等基于行的操作。......

阅读全文(3665) | 评论:0

<C++语言命令详解>第二章:C++的基本特征(2005-08-21 10:59:00)

摘要:指令与代码的区别:指令都是以#开始,以行尾结束。在源码文件中,在对文件编译之前先对指令编译。     C++语言中最基本的单元之一是表达式。一般来说,表达式最后都获得一个值。表达式可以是变量、常量、函数调用或可以是由小的表达式通过运算符连接起来的符合表达式。其中,赋值语句也是表达式。     C++中变量的五种作用域:局部变量(Local,函数内部,可变)、全局变量(Global函数外,模块内,可变)、静态变量(Static,函数内,但是其生存期一直到模块结束)、外部变量(External,模块间公用)和类作用域(变量的作用限制在类的对象中)。     静态函数只在模块内可见,而非静态函数在模块被包含之后可被其他模块看见。     只有将变量声明为外部的,且在其他模块包含本模块时,变量才可被其他模块看见。     出现问题:       struct card{ unsigned int rank: 4 ; unsigned int suit: 2 ; };       card cd, desk[52];......

阅读全文(3214) | 评论:0

<C++语言命令详解>第一章:C++的功能(2005-08-21 09:36:00)

摘要:在面向对象的编程结构出现之前,最明显的汇编语言结构是控制与数据相分离,内存中的数据与代码是分开的,除了偶尔的跳转,CPU大部分时间都是顺序执行代码,所以大段的代码结合成代码段,代码必须去寻求自己所需要的数据结构,如图/表;而面向对象的编程结构将两者融合为一体,形成一个类,它包含了对象的数据和行为。     JAVA从C++中借鉴了很多东西,它是面向Internet的未来语言。     VB的事件驱动模型是从C++的面向对象发展而来,因为C++有接受消息的接口的独立能力。     封装的结果是除了接口数据的共享之外,类的内部受到保护。 The New :     多态:分散化控制     重载:函数、运算符     封装......

阅读全文(2648) | 评论:0