2008年6月30日

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

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

posted @ 2008-08-01 15:32 清流琴音 阅读(75) | 评论 (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 清流琴音 阅读(91) | 评论 (0)编辑 收藏
 
指针中存有另一个对象的地址,使我们可以间接的操作这个对象。
指针的典型用法是构建一个连接的数据结构,例如:链表(list)和数(tree)。并管理在程序运行的过程中动态分配的对象。以及作为函数参数类型。主要用来传递数组和大型类的对象。
每个指针都有相关的类型。
不同数据类型的指针之间的区别不在于指针的表示上,也不是指针所持有的值(地址)。——对于所有类型的指针这两个方面都是一样的。不同之处在于指针所指的对象的类型上。针织类型可以指定编译器咋样解释特定内存上的指定的内容,以及该内存区域因该跨越多少内存单元。
posted @ 2008-07-08 14:43 清流琴音 阅读(94) | 评论 (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 清流琴音 阅读(622) | 评论 (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 清流琴音 阅读(117) | 评论 (0)编辑 收藏
 

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

posted @ 2008-07-07 10:33 清流琴音 阅读(112) | 评论 (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 清流琴音 阅读(151) | 评论 (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 清流琴音 阅读(220) | 评论 (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 清流琴音 阅读(154) | 评论 (0)编辑 收藏