2008年6月17日

规则:
应该将修饰符*  和 &紧靠变量名。例如:int  *a;  int &a;
类的版式:
类可以将数据和函数封装起来,其中函数是表示类的行为。也可以称为是服务。类提供了关键字public ,protect ,private用于声明哪些是公共的,哪些是保护的,哪些是 私有的。这样可以让类隐藏必要的东西。
类的版式主要有两种版式:
 (1):第一种将privte类型的数据 写在前面,将public类型的数据写在后面。采用这种版式的程序员主张“以数据为中心,”重点关注类的结构。
 (2):第二种版式是将public类型写在前面。将private写在后面。这种版式的程序员主张“以行为为中心”。重点关注的是类应该提供什么样的接口(或者服务)。
我建议大家采用“以行为为中心的”的这种类的 版式。因为这样设计类的时候。首先考虑的类可以提供什么洋的服务。而且方便用户阅读。

posted @ 2008-08-05 15:24 清流琴音 阅读(306) | 评论 (3)编辑 收藏
 
空行:
空行起着分隔程序段落的作用。
(1):在给个类的声明之后,函数的定义之后,都要加上空行。
(2):在一个函数体内,逻辑关系密切的相关语句之间不可以加上空行。
代码行:
(1):一行代码指做一件事情。例如:只声明一个变量。
(2);if ,for while,do等语句自占一行。执行语句不能紧跟其后。
建议:在定义变量的同时。初始化该变量。
如果变量的引用和定义的地方比较远,那么很容易就会忘记了变量的初始化。如果引用了一个没有初始化的变量,那么很有可能就会引起错误。
代码行内的空格:
(1);关键字之后要有空格。向const ,virtual,case等关键字后面至少要留一个空格。否则的话,无法辨认关键字。象if.while, for等关键字后面紧跟一个空格在跟“(”以显示关键字的。
(2):函数名之后不要留空格,紧跟“(”以和关键字区别。
对齐:
程序的分界符“{”和"}"应该独占一行并且位于一列。

posted @ 2008-08-01 15:32 清流琴音 阅读(126) | 评论 (0)编辑 收藏
 
头文件由三部分组成:
1:头文件开头出的版本和版权的 声明。
2:预处理块。
3:函数和类的结构声明等。
规则:
(1): 为了防止头文件被重复的引用,应该使用#ifndef/define/endif结构产生与处理模块。
(2):用#include<filename.h>来引用标准库的头文件(编译器将从标准库目录开始搜索)。
(3):用#include"filename.h"来引用非标准库的头文件(编译器将从用户工作的目录开始搜索)
建议:头文件中一般只存放“声明”,而不存放“定义”

定义文件的结构:

定义文件的 内容有由三部分组成:
(1):  定义文件开头处的版本和版权;
(2):对一些头文件的引用;
(3):程序的实现体(包括数据和代码)

头文件的作用:
(1):通过头文件来调用库功能。在很多场合源代码不能(或者不准)提供给用户。只提供给用头文件或者二进制的库。用户只需要按照头文件中的接口的声明来调用库功能。而不必关心接口是如何实现的。编译器会从库中提取相应的代码。
(2): 头文件可以用来加强类型安全检查。如果某个接口被实现或者被实用的时候,其方式和在头文件中的声明不一致的时候,编译器就会报错。这一简单的规则可以大大的减轻程序员调试和改错的负担。
目录结构:
如果一个软件的头文件比较多(超过10个),就应该把头文件和定义文件分开。分别保存在不同的目录之中。以便于维护。
例如:可以将头文件保存在inluude目录之中。将定义文件保存在source文件之中。
如果某些头文件是私有的,不会被程序直接引用,为了加强信息隐藏。那么可以把这些头文件和定义文件放在同一目录之中。
posted @ 2008-08-01 15:13 清流琴音 阅读(156) | 评论 (0)编辑 收藏
 
指针中存有另一个对象的地址,使我们可以间接的操作这个对象。
指针的典型用法是构建一个连接的数据结构,例如:链表(list)和数(tree)。并管理在程序运行的过程中动态分配的对象。以及作为函数参数类型。主要用来传递数组和大型类的对象。
每个指针都有相关的类型。
不同数据类型的指针之间的区别不在于指针的表示上,也不是指针所持有的值(地址)。——对于所有类型的指针这两个方面都是一样的。不同之处在于指针所指的对象的类型上。针织类型可以指定编译器咋样解释特定内存上的指定的内容,以及该内存区域因该跨越多少内存单元。
posted @ 2008-07-08 14:43 清流琴音 阅读(165) | 评论 (0)编辑 收藏
 
变量名,即变量的标识符,可以由字符,数字,以及下划线来组成。他必须以字符或者下划线来开头,并且区分大小写。
语言本身没有对变量名做什么限制。但是为了用户着想,他不应过长。
c++保留了一些词用作关键字。关键字标识符不能在作为标识符在程序中使用了。
对于命名对象有很多已经普遍接受的习惯。主要考虑的因素的是程序的可读性。
第一:对象的命名一般用小写。
第二:标识符通常用容易记忆的名字。
第三:对于多词构成的标识符一般在词的中间加上下划线。
对象的定义:
一个简单的对象的定义由一个类型指示符后面加上一个名字构成,以分号结束。
例如: int aaaaa;
当同类型的多个标识符被定义的时候,我们可以在类型指示符后面用逗号隔开。
一个简单的定义指定了变量的类型和标识符。他并不提供初始值。
如果一个变量是在全局域(globe scope)中定义的,那么系统会保证给他一个初始值0。如果一个变量是在一个局部域中定义的,或者通过一个new 动态分配的,那么系统不会向它提供初始值0。这些对象被称为未初始化(uninitialized),未初始化的对象不是没有值,而是对象的值未被定义。
因为使用未初始化的对象是个很常见的  错误,并且很难被发现。所以建议为每个定义的对象进行初始化。
类机制通过缺省构造函数提供了类对象的自动初始化。
例如:
int  main()
{
int val;////////未被初始化的值。
string  project;//////通过string类的缺省的构造函数进行了初始化。
}


val是一个未被初始化的局部变量。
但是project是一个已经被初始化的类对象——被string类缺省的构造函数自动初始化。
初始化一个值可以在对象定义的时候进行。
c++支持两种形式的初始化。
第一种是使用赋值符号的现实的操作。
如:
int val=111;
string  project="ssssss";
隐式形式中,初始化值被放在括号中。
int val(111);
string project("sssssss");
在对象的定义之中,当对象的标识符在定义中出现后,对象名马上就是可见的了。因此用对象初始化他自己是合法的,只是这样做不是明智的。
例如:int val=val;///////合法,但是不是明智的。
另外,每种内置数据类型都支持一种特殊的构造函数。可将对象初始化为0。
/////设置val为0。设置dval为0.0。
int val =int();
double dval=double();
下列的定义中:
int()
vector <int>ival(10);
函数int()自动被应用到ival包含的10个元素上。
对象可以用任意复杂的表达式来初始化,也可以用返回值
posted @ 2008-07-08 14:26 清流琴音 阅读(692) | 评论 (0)编辑 收藏
 
变量为我们提供了一个有名字的内存存贮空间。可以通过程序对其进行 读写,处理操作。
c++中给个符号变量都有一个符号类型与之对应。这个类型决定了相关内存的大小,类型,布局,能够存贮在该内存值的范围。以及可以以用到其上的操作集。我们也可以把变量说成是对象(object)

变量和文字常量都有存贮区,并且都有相关的类型。区别在于变量是可以寻址的(adressable)常量文字是不可以寻址的(nonadressable),每一个变量都有两个值与之联系着,
1:数据值。存贮在内存的某个存贮区之中。有时候这个数据值也被称为是右值(rvalue).我们可以认为右值是被读取的值。文字常量和变量都可以被用来做右值。
2:它的地址值。即存贮它数据值的那块内存的地址。它有时候被称为左值(lvalue)。我们也可以认为左值的意思是位置值。文字常量不能被用作左值。
变量的定义会引起相关内存的分配。因为一个对象只能有一个存贮位置,所以一个对象只能被定义一次。如果在一个文件中定义的对象需要在另一个文件中被访问,那么就会出现问题。
在c++中,对象在使用之前必须知道对象,引用一个未知的对象会引起编译器的错误。
如果一个对象在另一个  文件中声明着,我们想在这个文件中来使用这个对象,但是又不能在这个文件中在声明相同的对象。那么我们可以使用extern关键字来声明这个对象。
例如; file module.c
 string aaaaa;
///定义了对象aaaaa



file  module1.c
////需要使用对象aaaaa.,
////声明对象aaaaa,使程序知道它。但是又不能引入第二个定义。
extern string aaaaa;
对象声明是使程序知道对象的类型和名字。它由关键字extern后面跟对象的类型和对象的名字构成。
声明不是定义,不会引起内存的分配。实际上它只是说明了在程序之外的某处有这个变量的定义。
虽然一个程序中只能包含一个对象的定义,但是可以包含很多的对象声明。
比较好的做法是:   不是在每个要使用的文件中都单独提供一个声明。而是在在头文件中声明这个对象,然后在需要声明这个对象的时候包含这个头文件就好了。按照这个做法。如果需要修改对象的声明只需要修改一次。就能维持多个使用这个对象的声明文件的一致性。



posted @ 2008-07-08 10:49 清流琴音 阅读(181) | 评论 (0)编辑 收藏
 

面相对象的程序设计扩展了给予对象的程序设计。可以提供类型和子类型的关系。这个是通过一种称作继承(inheritance)的机制来实现的。

posted @ 2008-07-07 10:33 清流琴音 阅读(174) | 评论 (0)编辑 收藏
 

c++預定了一組數值數據類型。可以用來表示整型,浮點型和單個字符。此外還預定了表示字符串的字符數組。
1:字符型char:通常用來表示單個字符和小整數。它可以用一個機器字節來表示(即8位表示)。
2:整型int  短整型short ,長整型long分別表示不同長度的整數值。典型的情況下:short用半個字表示(即16位)。int 用一個字表示(即32位。)long用一個或者兩個字表示。(在32位的機器中通常int 和long的通常長度相同。)
3:浮點型flont ,雙精度double和長雙精度。長雙精度long double 。分別表示單精度浮點數。雙精度浮點數和擴展精度的浮點數。典型的情況下,float用一個字表示。double用兩個字表示,long double用三個或者四個字表示。
char ,int, float , long 稱為整值類型(intergral  type)。整值類型可以有符號也可以沒有符號。在有符號的類型中。最左邊的位是符號為。余下的位代表數值。。在無符號的類型中,所有的位表示數值位。
如果符號為被設置為1。那么數值被解釋為負數。如果符號為被設置為0。那么數值位被解釋為正數。
一个8位有符号的char 表示-128---127之间的值。而一个无符号的char则表示0--255之间的值。
当一个值。例如1。出现在程序的时候,我们称它为文字常量。称他为“文字”是因为我们只能以他的值的形式来指代它。称之为常量是因为它的值不能被改变。每个文字都有相应的类型。文字常量是不可寻址的(nonadressable)。尽管他的值也被存储在机器的某个内存之中。但是我们没有办法来寻找它的地址。
整数文字常量可以被写成十进制。八进制,十六进制的形式。(这不会改变该整数的位序列)。例如:20可以写成以下的方式:
20/////////十进制形式
024/////八进制
0x14////十六进制。
在整型常量前面加上0。该值将被解释成一个八进制数。而在整形常量的前面加上0x,则该值将会被解释成十六进制数。
在缺省的情况下,整形常量被当作一个int的有符号的整数。
我们可以在一个文字常量的后面加上一个“L”或者"l",将其指定为long类型。
类似的,我们在文字常量的后面加上“u”或者“U”。表示一个无符号的数。
此外,我们还可以指定无符号long类型的数。例如: 1UL.
单词true 和false是bool型的文字常量。
可以打印的文字常量可以用单引号''括起来例如:
'A','S'...等。
不能够直接打印的字符,单引号,双引号,和反斜杠就i可以用转义序列来来表示(转移序列用反斜杠来开头)。
\n 换行符
\t水平制表符
\v垂直制表符
\b退格符
\r回车键
\a响铃建
\\反斜杠键
\?问号
\'单引号
\""双引号
另外字符文字前面可以加上“L
例如:L'a'
这个称为宽字符文字,类型为wchar_t.宽字符常量用来支持某些语言字符的集合。例如:汉语,日语等
这些语言中的某些字符不能用单个的字符来表示。
字符串常量由零个或者许多个由双引号括起来的 字符
不可以打印的字符由相应的转移序列来表示,而一个字符串文字可以扩展到多行。在一行的最后加上一个\,表示字符串文字在下一行继续。
如:"fdfdf fdfdf\dfdfdfsdffdfdfdf"
字符串文字的类型是常量字符数组。字符文字本身和 编译器加上的表示结束的(NULL),字符构成。
例如:'a'表示一个单个的字符a
"a"则表示一个字符a和一个空字符,
空字符是c和c++用来标记字符串结束的符号
正如宽字符文字。L'a'

也有宽字符串文字L"aaaaaaa"
宽字符串文字的类型是常量的宽字符数组。他也有一个等价的宽空字符作为结束的标记。
如果两个字符串和或者宽字符串在程序中相邻。c++就会把它们连接起来。并且在最后加上一个空字符,
例如:"one" "two" 则输出的结果为onetwo.
如果把一个字符串常量和一个宽字符串常量链接起来,那么结果会是如何呢?
"aa" L"SSS"
结果是未定义(undefine)------即没有这种这两种不同类型链接标定义行为。
使用未定义的程序被称为是不可以移植的。
虽然程序可以在当前的编译器下可以执行,但是不能保证相同的程序在不同的编译器下,或者在当前的白一起的以后的版本中,还能够正确的编译通过。
在本来可以正常运行的程序中来寻找这些是件很令人心烦的事情,所以我们建议不要使用未定义的程序特征。
posted @ 2008-07-04 15:35 清流琴音 阅读(191) | 评论 (0)编辑 收藏
 

正如我们看到的,尽管c++的数组支持容器机制。但是它不支持容器抽象的语义。为了在这个层次上编写程序。在标准c++之前。要么我们从某个途径获取这样的类。要么我们自己编写这样的类。
在标准c++中。数组类是c++标准库中的一部分。现在它不叫数组了,而叫向量(vector)、

当然向量是一个类模板,我们可以这样写:
vector<int> ivec(10);
vector<string>svec(10);
上面的代码分别定义了包含10个整型的对象的向量,和定义了包含10个字符串的对象的向量。
在我们实现的Array类模板和vector类模板的实现中有两个不同的区别;
vector类模板支持“向现有的数组元素赋值”的概念以及“插入附件元素的”概念---------即vector数组可以在运行时动态的增长。(如果程序员愿意使用这个特征的话。)
第二个区别是 : 更加广泛。代表了设计方法的重要改变。vector类不是提供一个巨大的“可以适用于向量”的操作集。如;store(),min().max()等。而是只是提供一个最小集;如:等于,小于,size(),empty()等操作。而一些通用的操作如:sort(),min().max(),find()。等操作是作为独立的泛型算法(generic algorthem)被提供的。
要定义一个向量我们必须包含相关的头文件。
#include<vector>
下面都是vector对象的合法定义。
vector<int>vecto;///////空的vector
const int size=8;
const int value=1024;
//size为8的vector
///每个元素都被初始化为0
vector<int>vecto(size);

//size为8的vector
///每个元素都被初始化为1024
vector<int>vecto(size ,value);
////vector3的size为8
///vector3的初始化值为ia 的4个值
int ia[4]={0,1,1,2};
vector<int>vector3(ia,ia+4);

////vector4是vector2的拷贝。
vector<int>vector4(vector2);
既然定义了向量,那么我们就必须遍历里面的元素。
与Array类模板一样。标准的vector类模板也支持使用下面的操作符。
例如:
#include<vector>
extern int getsiz();
void mumble()
{
  int size=getsize();
vector<int>vec(size);
for(int i=0;i<=size;i++)
{
 vec[i]=i;
/////,.............................
}
}
posted @ 2008-06-30 15:18 清流琴音 阅读(283) | 评论 (0)编辑 收藏
 

名字空间允许我们封装名字,否则的话,这些名字就有可能污染到全局的名字空间(pollute teh global namespce).一般来说,只有我们希望我们的代码被外部软件开发部门使用的时候。才会用到名字空间。
例如;我们可以这样来封装Array类,
namespace cplacple_primer_3E
{
 template <calss eyemly>
 calss Array{,,,,,,,,,};
////////////////////////

}
namespce后面的名字标明了一个名字空间。它独立于全局名字空间。我们可以在里面放一些希望声明在函数和类之外的实体。名字空间并不改变他们的声明意义。只是改变了它们的可视性。如果名字空间中的声明对于程序来说不是立即可见的。那么我们杂样来访问他们呢?我们就要用到限定修饰名字符.
格式如下:
namespce_idenerfier::entrityname
名字空间别名(namespce alias)允许用一个可替代的,短的,或者跟一般的名字来和名字空间来关联起来。
例如:
//提供一个更一般化的名字
namespce lib=cplacple_primer_3E
然后这个名字就会称为原始名字空间的同义词。
#include "cplacple.h"
int main()
{
 lib::Array{...........}

 }
别名也可以 用来封装正在使用的实际的名字空间。在这种情况下,我们可以通过改变别名的名字空间。
来改变所使用的声明集。而无需改变“通过别名来访问这些声明”。的实际代码。
using 指示符使名字空间中的所有的声明都是可见得。这样这些声明可以不加任何的限定的使用。
using和namespce都是关键字。被引用的名字空间必须已经被声明了。否则的话,会引起编译的错误。

using 声明提供了更为精细的名字可视化机制。它允许使名字空间中的单个的声明可见。
例如:
#include"IBM_Canada_Labaraory.h"
using  namespace IBM_Canada_Labaraory::Matriy
int main()
{
 //ok; IBM_Canada_Labaraory::Matriy

Matriy met(4,5);
//fail,错误。IBM_Canada_Labaraory::Array不可见
Array array(4,5);
}
为了防止标准的c++库组件污染用户定义的名字空间。所有的c++库组件都声明在一个称为std的名字空间中。
所以即使我们在我们的文本文件中已经包含了c++库头文件,头文件中声明的内容在我们的文本文件中也是不可见的。
例如:
在c++中下面的代码是不能被编译通过的。
#include<string>
///错误。string 是不可见的
string  current_string="asdf dfdff";
在string 头文件中所有的声明都包含在std名字空间中。
我们可以用“#include 指示符后面加上using 的办法使在<string>中的,在std中声明的组件,对于我们的文本文件是可见得。
例如:
#include<string>
 using namespace std
int main()
{
 //////////正确。string 是可见的。
  string current_string="asd fdfdf"
}
为了使在std中,声明的组件和名字在我们的文本文件中可见。using指示符通常被看作是一种比较差的选择方案。
在上面的例子中。指示符using ,使在string头文件中声明的,并且在std名字空间中的  组件在我们的文本文件中都是可见的。这又将全局名字空间污染问题带回来了。而这个问题就是std名字空间首先要努力避免的。
它增加了“c++标准库组件的名字”与“我们程序中声明的全局名字”冲突的机会。
现在有两种机制可以替代using指示符。来引用隐藏在std名字空间中的名字string.
第一种方法:
 可以使用限定的名字。
  #include<string>
/////正确。使用限定的名字
   std:: string current_string="afdfdfsdfs";
第二种方法:
 如下使用using 声明;
#include<string>
 using std::string;
 /////ok.上面的using声明使string可见。
 string=“dfdfdfafsdf”;
为了使用名字空间中的声明的名字。最好使用带有精细选择功能的 using声明替代using 指示符。

posted @ 2008-06-30 11:15 清流琴音 阅读(231) | 评论 (0)编辑 收藏
 
异常(exception)是指在运行的时刻程序出现反情况。比如:数组下标越界。打开文件夹失败,动态创建内存失败等。程序员一般有自己的异常处理方式。这导致个各种编码方式,。所以很难整合到一个程序中。
异常处理(exception  handing ), 为“响应运行时刻的程序“提供了一个标准语言级的设施。它支持统一的语法和风格,也允许每个程序员进行微调。异常处理                不需要我们在程序中处处显示的测试异常状态。从而可以将测试代码显示的抽取出来,放在指定的 标记的代码块中。因此 异常处理设施大大的 简化了程序的长度和复杂度。
异常处理机制主要构成如下:
1: 程序中异常出现的点。一旦识别出程序的异常,就会抛出异常(throw)。当异常被抛出的时候,程序就会被挂起,知道异常被处理完毕了。c++中,异常的处理有throw表达式来执行。
2:程序中异常被处理的点. 典型的程序的异常抛出和处理位于独立的 函数或者成员函数中。找到异常处理代码一般要展开程序调用栈(progam call stack ).一旦异常被处理完毕,及恢复程序的正常执行。但是不是在出现 异常的地方恢复,而是在处理异常的地方恢复执行过程。在c++中异常的处理用catch表达式来执行。
catch和try字句相关联。一个try块用一个或者多个catch子句将一条或者多条语句组织起来。
系统根据被抛出的异常和catch子句的异常类型的匹配的情况来选择catch子句。
系统把控制传递给catch子句体,其中的语句将顺序执行。完成后后,除非子句体中还抛出异常,否则的话,控制将会被传到程序的当前点上。
posted @ 2008-06-27 14:58 清流琴音 阅读(188) | 评论 (1)编辑 收藏
 
c++的模板提供了一种机制,它能够把函数和类内部的数据和值参数化。这些参数在其他地方不变的代码中用作占位符。以后,这些参数会绑定在实际的数据类型中。可能是内置的数据类型,也可以是用户自定义的 类型。
posted @ 2008-06-27 14:51 清流琴音 阅读(110) | 评论 (0)编辑 收藏
 
在c++ 中,被继承的类称为基类(base class)新类  被称为从基类中派生(derived)来的。我们把它叫做派生类或基类的子类。子类和基类共享公共的接口(common interface--)-----共有操作的公共集.由于共享公共接口,就允许子类和基类在程序内部可以互换使用。而无需考虑对象的类型。从某种意义上说,公共接口接口封装了子类型中与类型相关的细节。类之间的类型和子类型形成了继承和派生层次关系。
在继承的机制下有多个  类的提供者:一个提供基类的实现(可能还提供一些派生类的实现。另外一个或者多个提供者在集成生命周期内提供派生类)。子类的提供者经常要访问(并不总是)基类的实现,为了提供这种能力,同时也为了能够还要防止对积累的一般性的访问,c++中提供了另一种访问级别:保护。在类的保护区域的成员函数和数据成员只提供给它的派生类使用,放在基类的数据成员和数据成员只能被它自己使用,它的派生类也不能使用使用它。

             
posted @ 2008-06-27 10:41 清流琴音 阅读(119) | 评论 (0)编辑 收藏
 

更一般的,c++支持函数重载(funtion  overloding)的机制。c++允许两个或者两个以上的函数具有相同的命名字。限制条件是参数的不同,可以是参数的类型或者数目的不同。根据不同的参数表。编译器就可以区分开调用哪个函数。
重载函数和非重载函数在运行时刻的行为是一样的。只是重载函数在运行的时候,会花费时间来决定到底用哪个函数。如果c++不支持函数重载的话。那么我们就必须为每个函数设置不相同的名字。
如果在类的体外进行成员函数的定义的时候,就必须指出这个成员函数属于哪个类。这个可以通过类的域操作符(calss  scope operator)来实现。
例如:Inarry::
":"冒号操作符被称为域操作符。
当与一个类相连接的时候。它就成为一个域操作符了。
我们可以非正式的把与看作是一个可视的窗口。非全局域的文件在它的这个文件中都是可见的,在一个函数体内定义的对象是局域的,它只在这个函数体内可见。每个类维持一个域。在这个域之外,它的成员是不可见的。类域操作符告诉编译器。域操作符后面的内容是可以在这个域中找到的。
引用:引用是一种没有指针语法的指针。与指针一样,引用提供对对象的间接访问。
类机制还支持特殊析构成员函数(destructor member funtion )每一个类对象在最后一次被使用之后,析构函数就会被自动调用。
我们在析构函数前面加上~线来标识。一般来说,析构函数释放类对象和在构造函数中所获得的资源。

posted @ 2008-06-26 11:56 清流琴音 阅读(158) | 评论 (0)编辑 收藏
 

基于支持对象的类的形式为:
class classname
{
 public////////公有操作集合
private:
//////私有实现代码

}
这里的class,  pulic。和private 是c++的关键字。classname是一个标识符,用来命名类名。以便以后引用该类。
类名代表着一种新型的数据类型,我们可以像定义内置的数据类型一样来定义对象。

例如:
Inarry    inaaay;////定义一个单个类Inarry的对象inaaay;
Inrry *inarry=new Inrry;///////定义一个指向Inrry类的对象的指针。
类的定义包含两个部分:
类头( class head)有关键字class和类名组成。类体(class boday)有花括号括起来。以分号结束。
类头本身也做类的声明。
类体包含成员定义和访问标签。如:public和private。成员定义主要包括:“该类主要实现什么洋的功能,”以及   “代表类抽象所需要的数据”这些操作称为成员函数(member funtion)。或者称为方法(methord)。
程序设计中一个常见的错误是使用先前没有正确被初始化的对象。实际上这是一个十分常见的错误。所以c++为用户定义的类提供了一种自动初始化机制:类的构造函数(calss  constructor)
构造函数是一种特殊的成员函数。专门用于初始化对象,如果构造函数被定义了。那么每个对象在应用的时候,该构造函数就会被自动的应用到该对象上。构造函数由类的提供者来定义。既我们提供类的定义的时候。就必须定义类的构造函数。
为一个类定义一个构造函数是类设计必不可少的一部分。
为了定义一个构造函数。我们只要  给出一个和 类名字相同的函数就可以了。
不能指定构造函数有返回值。可以定义很多的构造函数在一个类中。
尽管她们具有相同的名字,但是只要编译器可以根据参数区分他们就可以了。
更一般的





posted @ 2008-06-24 14:22 清流琴音 阅读(174) | 评论 (0)编辑 收藏
 
在c++中,内存可以是静态分配的——编译器在处理源代码的时候就分配,也可以是动态分配的---程序在 运行的时候调用所需要得库函数进行分配。这两种分配方式各有个的优点。由于静态内存分配是在程序运行之前就分配了内存,所以执行的效率就很高。但是缺乏灵活性。它要求知道程序在之前就知道内存的类型和数目。
例如:
利用静态分配的字符串数组,我们就无法很容易的处理和存贮任意的文本文件。一般来说存贮未知的的数目的元素,需要动态分配内存的灵活性。
例如:以下的定义:
int ival=1024;
指示编译器分配足够的内存来存贮一个整型值。该存储区与名字ival相关联。然后用1024区初始化该存贮区,这些都是在程序之前完成的。
c++支持用指针类型来存放对象的内存地址值。
例如:
为了声明一个存放ival内存地址的的指针类型。我们可以声明如下:
int *print;//////一个指向int类型的指针。
c++预定一个专门取地址的操作符(&),当他应用于一个对象上的时候,返回的是该对象的地址。
因此,为了将ival的地址值赋值给print,我们可以写为:
int*print;
print=&ival;///把ival的地址值赋值给print
为了访问print所指向的内容。我们必须先用解引用(dereference)操作符(*),来先解除的引用。
例如:我们通过print间接的给ival加1;
*print=*print+1;
等价于:
直接对 ival进行操作
ival=ival+1;
在c++中指针主要是用来管理和分配动态分配的内存。
对象的分配可以通过两个不同的版本来实现。
第一个版本用于分配特定类型的单个对象。
int*print=new int 1024);
分配了一个没有名字的int类型的对象,对象的初始化值为1024。然后表达式返回对象在内存中的地址。
接着这个地址用来初始化指针对象print.    对于动态分配的内存。唯一的访问方式是通过指针来访问。
例如:
new的第二个版本,用于分配特定的类型和维数的数组。
int *pia=new int[4];
分配了一个含有4个元素的整型数组。不幸的是我们没有办法给动态分配的数组每个值显示的指定一个初始值。
分配动态数组,一个常令人困惑的问题是,返回值只是一个指针。与分配单一对象的返回值是相同的。
posted @ 2008-06-24 10:11 清流琴音 阅读(562) | 评论 (0)编辑 收藏
 
数组是一组具有相同数据类型的元素的集合。
c++为基本算术数据类型提供了内置的支持。同时他也支持双精度和单精度的数据支持。除此之外c++还支持布尔类型,以及用来存放字符集中单个元素的字符支持。
在内置数据类型和标准库类类型之间的是复合数据类型(compuond type)特别是指针和数组类型。
数组(array)是一个顺序的容器.它包含单一类型的元素。
例如:序列
0 1 1 2 3 5 8 13 21
代表菲波那契序列的前9个数。(只要给出前两个数据,后面的数据就是前两个数据的之和。)
a[8]={0,1,2,3,4,5,6,7}
当a[9]的时候,就会出现一位偏移错误(off-by-one):
通常我们用循环来遍历数组中的元素。
例如:下面的程序初始化了一个数组。前9为分别为0---9
int main()
{
  int ia[10];
  int idex;
 for(idex=0;idex<10;idex++)
{
 ia[idex]=idex;
}
for(idex=9;idex>=0;idex--)
{
 cout<<ia[idex]<<"";
cout<<endl;
}
}
c++虽然对数据类型提供了内置的支持。但是这种支持只是限定于“读写单个数组元素”。c++不支持数组的抽象(abstracion),也不支持对整个数组的操作.我们有时候希望对整个的数组进行操作。例如:把一个数组赋值给另一个数组。对两个数组进行比较。。想知道数组的大小。
例如:给出两个数组,我们不能直接用赋值操作符,把一个数组的值拷贝到另一个数组中去。
比如:
ia1[10], ia2[10]
ia1[10]=ia2[10];/////错误。不能直接把一个数组的值通过赋值运算符赋值给另一个数组。
如果想把一个数组的值赋值给另一个数组我们必须自己编写程序。
for(int idex=0;idex<10;idex++)
{
  ia1[idex]=ia2[idex];

}

而且数组类型并没有自己的意识。它并不知道自己的长度,我们必须另外记录数组的信息。当我们希望把一个数组作为参数传递给一个函数的时候,问题就出现了。在c++中,数组不同于整型类型和浮点类型,它不是c++的一等公民(first——class),它是从c语言中继承而来的,它反映了数据与对其进行操作的算法的分离。这正是过程话程序的特点。
posted @ 2008-06-23 10:28 清流琴音 阅读(216) | 评论 (1)编辑 收藏
 
c++的输入输出功能是由输入输出流(iostream)库提供的,输入输出流库是c++面向对象类层次的一个结构,也是c++库的一部分。
终端的输入也称作是标准的输入(standard input ),与预定义的iostream 对象sin 绑定在一起。
终端输出,也称作是标准输出(standard output ),与预定义的iosream的对象cout 绑定在 一起。
第三那个预定义对象cerr,也称为标准错误。也终端绑定。cerr通常用来给程序用户提示错误的 信息,以警告的信息。
任何想使用iostream库的文件都要包含,相关的头文件。
#include< iostream.h>
输出操作符<<用来把一个值导向cout标准输出或者cerr标准错误上。
例如:
cout<<"\n"; 中的“\n表示换行符(new line),输出换行符的时候,它结束当前的行,并将输出导向下一行。
除了显式的使用"\n"进行换行外,还是可以使用预定义的iostream 操作符endl。进行换行。
操作符在iostream上,进行的是一个操作,而不只是简单的提供一个数据。 
文件的输入和输出:
iostream库也支持的输入和输出。所有能应用在标准当输入和输出的上的操作,也都可以应用在已经被打开的输入和输出文件上。
为了打开一个文件供输入和输出,除了包含iostream外,还必须包含头文件,
#include<fstream>
为了打开一个输出文件,我们必须声明一个ofstream类型的对象。
ofstream outfile("name_of -files");
为了测试是否成功的打开一个文件,我们可以用下面的代码:
if(!outfile)
{
///如果文件不能打开,值为false

}
类似的,如果我们打开一个文件供输入,那么我们必须声明一个ifstream的对象。
ifstream infile("name-of  _files")
if(!infile)

例如:
c++中
从一个文本中1.txt中读内容到2.txt中,
#include<iosrteam>
#include<ftream>
#include<string>
using spacename std;//////注意这里。


posted @ 2008-06-21 16:31 清流琴音 阅读(160) | 评论 (0)编辑 收藏
 

注释是用来帮助程序员来读程序结构的与语言。它是一种礼仪,可以用来说明变量的意义或者用来某一段难懂的代码。注释不会增加可执行代码的长度,在生成可执行代码之前编译器会将注释的部分从程序中去除的。
c++中有两种注释符,一种是注释对(/**/)。与c语言一样,注释的部分放在/**/之间。编译器会将/**/之间的代码当作注释部分,注释的可以放在任何位置。可以含有制表符,空格, 可以跨几行。
第二种注释就是//双斜线。它可以注释单行的内容,注释符右边的内容都会被当作注释的内容而被编译器忽略。

posted @ 2008-06-21 11:14 清流琴音 阅读(152) | 评论 (0)编辑 收藏
 
assert()是c语言标准库提供的一个通用的标准库预处理器宏。在代码中经常用assert()来判断一个必须的前提条件。例如:要打开一个文件,我们必须先知道合格文嘉你的名字,然后在可以打开为了使用assert()必须包含与之对应的头文件
#include < assert.h>
下面是一个简单的例子:
assert(filename!=0);
判断是否文件的名字为0。建兴断言,如果文件的 名字为0,那么断言失败,输出错误的诊断信息,然后中止程序。
assrt.h是c标准库头文件的c名字。c++程序可以通过使用c的库头文件的c名字或者c++的名字来使用它。
这个头文件的c++名字是cassert. c库头文件的c++名字总是以c开头,后面跟的是c名字去掉.h的名字。(因为c++中,头文件的后缀各不相同,所以标准的c++没有指定头文件的后缀).
使用c库头文件名字和使用c++的名字,那么#include 预处理器的效果也是不一样的。
例如:下面的#include指示符;
#include<cassert>
当我们把这个头文件读入我们的文本文件中的时候,头文件中的内容 好似不可见的。因为所有的c++库名字是在std名字空间中定义的。所以我们的文本文件是不可见的。除非我们使用using指示符显示地使其可见。
using  namespace  cassert;
使用c库的头文件就可以直接的在文本文件中使用assert()。而无需使用using指示符了。


posted @ 2008-06-21 11:12 清流琴音 阅读(433) | 评论 (0)编辑 收藏
 
编译c++的时候,编译器自动定义了一个预处理器名字_ _cplusplus,(注意前面有两个下划线)。
因此我们可以根据它来判断程序是否为c++程序,以便有条件的包含代码。
例如:
#ifdef _ _cplusplus
//不错,我们要编译c++
//extern "c"我们在第七章在讲解
extern"c"
#endif
min(int ,int );
在编译c的时候,编译器定义一个_STDC_,当然_ _cpluscplus和_STDC_不会同时被定义的,
另外两个比较有用的名字是_LINE_和_FILE_。其中_LINE_是指已经编译的行数。_FILE_包含正在被编译的文件的名字。
另外两个预定义的名字是:_TIME_和_DATE_它们分别包含被编译文件的时间和日期。
时间的格式为:hh:mm:ss
例如:如果你是在正8点17分编译这个文件,那么时间表示为8:17:00。如果那天刚好为1998年10月23号,那么日期就为:oct23 1998
如果当前的或者文件的名字发生了变化,那么预定义名字_LINE_和_FILE_就会变化,其他的预定义名字在编译期间不会变化的。她们的值也不能被修改




posted @ 2008-06-21 10:44 清流琴音 阅读(110) | 评论 (0)编辑 收藏
 

头文件通过预处理器标识符(include)而成为我们程序的一部分。预处理器标识符用“#”来标识。这个符号放在程序的最开始 的第一行的位置上。处理这些标识符的程序称为预处理器(preprocessor),一般绑定在编译器中。
include 指示符读入指定文件的内容,它有两种格式:
#include<iostream>
#include"iostream"
如果文件名用"<"和 ">"括起来。那么表示这个文件是一个工程文件或者标准的头文件。查找过程会检查预定义的目录。我们可以通过设置搜索路径环境变量或者命令行选项来修改这些目录。
如果文件是用引号括起来的,就表示这个文件是用户自己提供的,那么查找这个文件的时候,就可以从当前的目录开始查找,
被包含的文件可能还会包含#include,一个同文件可能会被同一个原文件多次的包含。条件指示符可以防止这种头文件被重复包含的情况。
例如:
#ifndef   BOOKSTORE_H
#define BOOKSTORE_H
/*bookstore.h的内容*/
#endif
条件指示符#ifndef用于检查预编译器常量BOOKSTORE_H是否已经被定义了(习惯上我们把与编译器常量用大写表示)。如果BOOKSTORE_H没有在前面定义的话,那么#ifndef 的值为真。那么#ifndef 和#endif中间的语句

将会被执行,否则的话,之间的语句就会被忽略。
为了保证头文件只被处理一次。把如下的的头文件放在#ifndef的后面。
#define指示符放在#ifndef的后面。这样头文件在第一次包含的时候,BOOOKSTORE_H就被定义了,那么以后如果在出现包含头文件的情况,则 #ifndef的值就为假了。
只要不存在“两个必须包含的头文件使用同一个预编译器常量”这种情况,那么这种机制就会很好的运行。
#ifdef指示符用来判断一个预定义器常量是否已经被定义了,以便有条件的包含程序代码。

注意:
#ifndef条件指示符和ifdef指示符的区别。
前者用于防止头文件被重复包含,而后者则是为了判断一下一个预定义器常量是否被定义了。


我们在编译程序的时候,可以使用-D,在——D的后面写上预处理器常量的名字,这样就可以在命令行中定义一个与处理器的常量了。
$CC -DBOOKSTORE_H   main.c
也可以用#define指示符来定义一个预处理器的常量。


posted @ 2008-06-17 14:58 清流琴音 阅读(444) | 评论 (2)编辑 收藏
 

我们的程序是由算法和数据组成的。算法是(就是将指令组织起来实现特定的功能),
在c++语言中,动作 被称为表达式(expression),以分号结尾的表达式称为语句。在程序中最小的单元是语句(statement).
 函数:把语句按照逻辑分组,就形成了某些单元,。这些单元称为函数(funtion)。
函数由四个部分组成:函数返回值的类型,函数名,参数列表,函数体,前三个组合起来称为函数原型(funtion prototype).
函数的参数由一个或者多个逗号隔开,由一个小括号括起来。函数体由一对花括号括起来。
return 语句是c++语句提供的预定义的语句,它提供了一种中止函数执行的方法。当return返回一个值的时候。例如:0 ,就表示这个函数返回了这个值(return value)。在标准的c++中当函数没有显示的返回值的时候,默认的函数返回值为0。
void 用来指定一个没有返回值的函数。
#include 是预处理器指示符(preprocessor directive)
在c++标准库中的名字。如:cout 不能直接在程序中使用,除非在预处理器标识符:#include<iostream>的后面使用 using  namespce std;
这条语句被称为using 指示符(using directve),c++标准库中的名字在我们的程序的文件是不可见的,它们都是在一个名字空间中声明的。我们只有显示的使用它们。这样的话,这些声明在名字空间中的名字才有可能在我们的文件中可见。using 告诉编译器使用在std名字空间中的名字。
编译器的一部分的功能是:分析程序代码的正确性,另一个功能是转换正确的程序代码。这种转换称为代码的生成(code generation),一般的情况下这些会生成汇编指令或者目标代码。这些目标代码可以被运行这些程序的计算机所理解。
成功编译的结果是一个可执行的文件。
c++定义了一组内置的数据类型,这些数据类型是:整型(int ),浮点型(float),布尔型(ture,和false ),字符类型,
在这些内置的数据类型之间可以隐式的发生转换(conversion).
c++标准还提供了一组扩展的数据类型。字符串类型(string),复数类型(complex number ),列表(list),向量(vector).



posted @ 2008-06-17 14:19 清流琴音 阅读(169) | 评论 (0)编辑 收藏