C++ Primer读书笔记2(经典收藏)

标题:函数再
函数是C++提出来的概念,但是在C中却未必没有。比如“1+3”“1.0+3.0”然都是加法,做的却不是同的操作:编译器要因操作数的不同而用不同的加法操作。只是C言中除了内部量可以参与运算以外,没有这么高深的概念。构体也只是内存数据的组织方法,而不整个构体的理。所以,在C编译器明明做了似于重的事情,却可以像雷做好事不留名
  C++展出了,并且予了很高的期望,象也能像内置象一参与一切运算。那,就拿加法运算来编译器如何知道类对象的加法该调用哪一个详细的操作代?于是,即使不出普通函数的重,至少运算符是要重的。
  林博士在《高C++/C程指南》中函数的必要性提了另一个理由:的构造函数名称必名相同,而常要定多个不同的构造函数。那就只好重了。
  于普通程序,我完全可以不用考这么深。重函数至少还带来了另一个好:不用记忆多个不同的函数名了,也不用函数起名而汁了。不书还给出了一个建:并不是任何候都有必要重函数的,有的候不同的函数名可以直来好多信息,用重只是牲了名称中的信息。
 
标题::重函数的概念
引用:出在相同作用域中的两个(可以是两个以上——猫注)函数,如果具有相同的名字而形参表不同,函数。
  本节开头第一句出了重函数的定:重函数必符合两个条件:一是出在相同的作用域中、二是函数名字相同而形参表不同。
  其中第一个条件一般人往往是不去想的,其函数名相同而作用域不同的函数大大存在,比如在MFC中就有。它是完全不相干的函数。
  第二个条件可以详说一下:函数名字相同当然不在下,是函数被称的根源。之于形参表不同,可能表在形参个数不同、可能表在形参型不同、可能表在形参序不同。
  如果要可以不是重函数的情况。
  一、如果既在同一作用域下、名称也相同、形参表也相同,后者被视为前者的重声明。——函数可以重声明,因函数的声明并不生目,但是函数的定不允
  二、如果既在同一作用域下、名称也相同、形参表也相同,但是返回不同,后者被视为错误的声明。函数不可以只凭返回来区分,因为调用函数的候只凭名称和形参来选择函数,而不凭返回。再究其原因,一是因函数的返回可以被弃;二来即使不弃,将返回值赋予另一个量之前没必要检查我需要什么样的返回,而能否赋值也与函数本身无
  三、有些候看起来形参表不同,实际上是完全相同的,本第229页讲了四组这样的例子:
Record lookup(const Account &acct);
Record lookup(const Account &);//
在于有没有形参命名
typedef Phone Telno;
Record lookup(const Phone&);
Record lookup(const Telno&);//
只是给类型取了个
Record lookup(const Phone&, const Name&);
Record lookup(const Phone&, const Name& = "");//
在于形参提供了默认值
Record lookup(Phone);
Record lookup(const Phone);//
在于是否const  
  其中第三可能会生函数的形参个数不同的假像,其可缺省的形参并没有减少形参的个数。第四有点不容易搞清:因有的候可以凭是否const来重,比如引用传递和指针传递
 
标题::文件的组织
一个程序往往由多个源文件成,些代究竟应该放在哪个源文件里、哪些代可以放在同一个源文件里、哪些代必需分放。是一个管理面的问题
  它是管理面的问题,是因为这些代组织往往没有惟一的准。但是它们还是有一定的律的。
  首先,件的维护是一个复杂的系工程。代组织应该有利于维护应该尽量把直接相的内容放在同一文件、不相的内容放在不同的文件里。如果些代码还和疏,那就要分不同的文件来存放了。
  其次,件的代是一个格的组织体系。不同的内容之可能是并列的,也可能有必要的先后系。于是在“#include”候要注意序。
  最后,也是最重要的一点,有些代在同一工程中可以重用(或必重用),有些代在同一个工程中只能出一次。可以重用的有的声明、函数的声明、量的声明等,不可以重用的是体、函数的体、量的定等。那,把可以重用的内容放在h文件中,把不可以重用的放在cpp文件中是一个好法。
  拿的声明和例,如果把一个的所有内容一古放在同一个文件中,将可能出现问题。因在其它用到类实例的地方都必须让类的声明,所以我往往在文件部加个“#include”体也被编译多次,在时产生冲突。
  在前文中曾提到,内函数是惟一允(也是必)在编译时让函数体可的的函数。所以内函数可以放在h文件中。C++规则中有一句正好与此照:在的声明中直接写出的函数被认为是内函数。
  Visual C++给类的文件起默,文件名往往与名一致。如果名由“C”开头文件会是除去开头“C”字以外的其它文字。如“CMyClass”,它的代存放在以下两个文件中:“MyClass.h”“MyClass.cpp”中。原因是VC++议类名以C开头,至于在文件名中不出现开头“C”,可能是出于微习惯
 
标题:的构造函数
引用:构造函数是特殊的成函数。
  笔:构造函数的确是一特殊的成函数。它的特殊性至少表在以下几个方面:一是它的用不用程序操心,只要类对象被建它就会被用,而且它不允被程序员显式地用。二是它是必需的,如果程序员偷懒编译器将自动创简单的构造函数。三是它的名字不用程序多考,直接与名相同。四是它没有返回
  下面详说这几个特性:
  一、它类对象被动调用,象可能有以下方法:程序中用声明量的句直接声明建,或者在程序中用new关键动态创建。方法都可以象,也都可以象数。只要有一个象被建,构造函数就被用一次。
  如果程序式地用构造函数那是不行的。正因如此,构造函数中有一特定的部分叫初始化列表,通它程序可以用基或成的构造函数。必竟设计千差万,如果某个的基或(和)成有多个构造函数,那该类指定用哪一个构造函数,否则类的功能将大打折扣。用构造函数不是程序的事,程序应该管也管不了。初始化列表解决问题而生,所以只有构造函数才有初始化列表,其它函数不能有。
  上面到的大打折扣究竟是怎的折扣呢?如果不能指定基和成用哪一个构造函数,那就只好让编译器去挑了,构造出来的象往往不符合要求,只好用基和成的其它函数,比如赋值函数或其它行参数定的函数——当然,基和成包含这样的函数。这样就浪源。
  二、包含构造函数——确切地是必包含无参数构造函数和拷构造函数——原因是因用是自的。如果两个函数根本就没有,你如何用?所以,C++也不含糊,你要是得写,它就帮你写一个简单的。简单就意味着至少要失一些功能,如果类设计得比较复杂(比如包含指操作)可能引起灾性事故。
  三、函数名与名一致。构造函数的名称是必特殊的,即使个特殊不表在与名相同,也必找到另一个规则实现。因要自动调些函数,你就必须让知道哪些函数是构造函数。
  第四个特性直接改C/C++言的一条规则C定,如果函数没有明指出返回型,那C认为返回int型。C言之所以可以有规则,一是因返回int的函数很多,二是因即使没有返回,也必指明void。当制定规则的人无法料到,C++中居然会出void都不是的返回的函数,void然表示不返回任何,必竟与构造函数的没有返回是两事。于是,C++定:在定或声明函数,没有式指定返回型中不合法的。当然的构造函数除外。
  构造函数的出有它的可行院厝恍浴?尚行允怯捎++包含成函数,既然可以包含普通的成函数,那包含特殊的函数自然也不在下。必然性是由于象往往必须经过特定的初始化。C++到来之前,C言中的数据型只是内置型。于内置象,如果忘了初始化,大不了象失去作用,但是不会致大的问题。比如一个int,无内存如何随机,它的取都不会超int能表达的范行运算也不会生危(溢出不能算危,即使初始化的数据也不能保不溢出,而且溢出只是一种逻辑问题)。但是在的这么简单了,忘了初始化往往将来运行错误。于其次都要考数据的初始化,不如把个初始化写成一的函数,动调用来得既安全又方便
 
 
标题:的成函数
C言中的构体最大的区就是可以函数,而构体只是一个内存。所以,要提就不得不提成函数。
  的成函数与普通函数(全局函数)相比,最根本的区实现的封装性。封装性的第一个表访问权限:都是函数,但是你能访问哪个不能访问哪个却可以定。第二个表是直,通过类(或指)来用函数,人的直就是提供的功能。你好像“Bird.Fly();”一目了然。
  在理解this以前要想底理解成函数是有困的,我就曾以例中保存了函数的副本。要不然,同一个的不同个函数有不同的效果呢?原来,在函数所有的形参之外,有一个不用你操心的参数this,它是一个指的目就是函数的用者。这么就明白了。
  函数形参表后加入const就成了“const函数这样的函数保用者自身不被修改。如CStringGetLength()函数,你只能取它的度,不能修改它的内容或度。加入const的作用倒不是怕用者修改,而是防止写函数的人不小心改象。因百密有一疏,万一在某个不修改数据的函数中改了数据(比如将“==”写成“=”),或者万一用了另一个非const的成函数都将可能引起错误。在写函数前就先加上const可以记编译器来帮你检查
  const加在形参表的后面得有些怪怪的,造成怪怪的原因就是因函数的形参表中没有this,也就没有能用const来修西了。林锐说大概是因其它地方都已被占用了并不是根本原因。
 
标题::内函数
函数应该了改善C言中的宏替的不足而生的吧。因宏替预编译中直接展的,展开过程中将生意想不到的果。典型的有“#define MAX(a, b) (a) > (b) ? (a) : (b)”“result = MAX(i, j)+2;”将被展开为“result = (i) > (j) ? (i) : (j) + 2;”然外面再加一括号可以解决以上问题,但是“result = MAX(i++, j);”被展后将i被自增1了两次。(以上例子摘自林博士的《高C++/C程指南》第66,林叫做边际
  C++用内来取代宏替,大大提高了安全性。然内函数也是编译时的,但是它能行安全检查的成函数(原因是内函数能够处this,宏却不能)。
  引用:内联对编译器来只是一个建编译器可以选择忽略个建
  笔:也就是,有些函数你想内编译器也不一定会采。因函数然减少了函数用的开销,却增加了程序的体
  内函数是唯一允许实体多次被编译的函数。原因是编译器必编译这个函数体,才能在编译函数用的地方行合理地展明在多个CPP文件成的工程中,可能有不止一个CPP文件中要有函数的体。既然这样,就放进头文件吧
本文本的评论有:
得象max()和以前的数越界一的事,都可以归纳为一句,那就是,C提供了大的工具,那些不会使用的人才会出现这种错误.个数越界也管理不好的,是去写武侠小.
比如火药发明了以后,可以用来炸山路什,道因有人用于,就怪个火功能不完善?
是这样的,我们不应该怪C标准不好,
虽然它不能让result = MAX(i++, j);这种问题得到解决,
产生i被自增两次这样的结果,程序员应该自己去避免。
但是,如果标准有进步了,我们倒是因为祝贺它一下。
 
 
标题::局部象与静局部
首先向明了名字的作用域象的生命周期两个概念,不,理解了就行了。前者是空概念:指程序还处在代码阶段的个名字的可,后者是时间概念:指程序运行程中象的存在时间
  函数的形参以及函数内部声明的象都是局部象,它的作用域就是函数内部,但是它的生命周期却未必是函数的程。看起来有点摸不着头脑,原因在于C++的函数中允存在以关键“static”声明的静态对象。
  也就是,静态对象是这样一个象:它的生命周期很,可以跨越函数的用,哪怕函数24用一次,它也是全天候存在的。但是要想访问她,却只有函数正在行的候才行。
  于以上特性,我专门写了两个测试函数,函数途返回局部象的引用或指
int& GetInt()
{
  int t=3;
  return t;//警告
}
int* GetInt2()
{
  int t = 3;
  return &t;//警告
}
  以上两个警告生的原因是函数返回了临时对象的引用或地址。但是如果将t的声明改成“static int t=3;”就不再示警告。
  静局部象似乎为节约统开销做了准。不认为这个特性不应该用。只有确有必要让对象生命周期跨越多次应该把它声明(比如统计函数被用的次数)。否将提高造成BUG的可能性,使高效率的程序成空中楼
标题::默认实
没什偷懒更舒服的了,所以我喜认实参的函数,我写允认实参的函数。
  在形参表中,如果允某些形参具有默认值按从右到左的方向排列。以上C++BASIC是一的,但是C++BASIC有一点区,就是在函数C++从右边开始缺省参,而BASIC却可以任意缺省而不次序(只要有逗号表示那里缺了个西即可)。所以,同样设计函数,C++BASIC要多考一个问题设计带有默认实参的函数,其中部分工作就是排列形参,使最少使用默认实参的表参排在最前,最可能使用默认实参的形参排在最后。
  形参的默认值竟究写在声明中体中?我曾经试过,在某些情况下写在声明中或体中一可行。但是,事上写在体中是错误的做法。只有当函数体和函数用在同一个源文件中,而且函数体在用前被编译时,将形参的默认值写在体中才可通过编译实际这种情况,函数根本就不用声明。
  将默认值写在体中不仅仅是能否通过编译问题还关系到程序设计的理念。一是函数的实现本来就与参数是否有缺省,所以,没有必要缺省在函数的定体中。二是参数的缺省可能会改然修改函数的声明比修改函数的定要方便。(《高C++/C编译指南》第63
  里,本书给了我一个大大的惊:原来默认实参的默认值还可以是任何表达式。以前,我一直是这样写的:“int GetInt(int i=3);”然没人跟我这样说过,但是我始后面的默认值只能是常量。想不到可以是需要求量甚至是更复杂的表达式:
int GetInt(const int i = 3);
int GetInt2(const int j = GetInt());//
居然可以这样
  学了,感C++ Primer》!
 
标题::函数的声明与
注:本中提到了声明两个。我倒是认为将后者改更好。
  函数的体就是实实在在的函数内容,它定了个函数怎样执行,没有什的。那函数么还要有声明呢?
  这样做的目的之一是告诉编译器:然你没有到函数本身,不知道函数是怎样执行的,但是我先告个函数的名称、参数与返回,你就先编译吧。至于个函数究竟干什,等到接的候再
  设计合理的程序,其代存放在不同的文件中,函数的体只能有一个,存放在某一个源文件中。其它源文件中如果要用到个函数,就在个文件中加入函数的声明。
  这样做的目的之二是函数的提供者与使用者往往不是同一个人,甚至不是同一个企。出于种种目的,函数的提供者可能并不想(或不必)使用者知道个函数的具体内容,只要使用者能用就行。这种情况下,函数的提供者只需要提供一个声明使用者即可。——C言的函数就是这样的。
  然而在需要用到函数的文件中加入函数的声明也有好法与笨法。将声明句重写一遍自然,但是这样做有两个明的缺点:一是烦琐、二是不易修改。所以,函数的声明应该放在文件中,哪儿要,就在哪儿包含。就好像我家没有摆许多盆花而是多面子。我在哪儿都能看到花,水却只要一盆。
  个理也适用于C++的声明写进头文件,而体却写程序文件。不同的是,的声明不像函数的声明那只有一句,而是一个完整的
 
 
标题:递归
引用:直接或用自己的函数称为递归函数。
  引用:递归函数必一个止条件,否函数将永远递归下去,意味着函数会一直用自身直到程序耗尽。
  初识递归候,的确有些不容易搞明白。得当的教科书为此画一个,用一来表示要AB、要B又要先C……,用另一表示算好了C就可以算B、算好了B就可以算A……例程序与一个图结合,如此实讲道理,要递归自然稍容易些。
  要写递归函数就得递归的妙用,要写没有错误递归函数悟其数学原理。我倒是这样的函数与数学归纳有些相通之。不同的是,数学归纳是先求界条件,再去往无方向归纳。而递归是从无方向向算的。函数如何行,与我如何写没有必然的系,于是,我在写程序的候也可以先写界条件。这样做可以在程序开头先把可能的问题给排除掉。远递归下去的可能性自然被降低。比如求乘的函数:
//
程序一、上的例子
int factorial(int val)
{
  if (val > 1)
    return factorial(val-1);
  return 1;
}
//
程序二
int factorial2(int val)
{
  if (val <= 1)
    return 1;
  return factorial2(val-1);
}
  程序二的写法与程序一没有区,但可以告自己递归止条件。防止一不小心就写了个
  似乎大多数递归函数都可以用循来解决。方法迁就了不同的象:循用少量的算机源、大量的人力来解决问题递归则用大量的算机源、少量的人力来解决问题。所以,在算机速度和存量都不大的年代,曾有人反对递归
  汉诺问题是只有用递归才可以解决的问题,其只有要求解汉诺塔的移动过程才必递归,如果只要求解移次数,那用循也不成问题
对本文本的评论有:
阶乘的函数写错了.
int factorial(int val)
{
  if (val > 1)
    return val* factorial(val-1);
  return 1;
}
晕,我忘了相乘了,哈哈。
 
标题:return
引用:return句用于束当前正在行的函数,并将控制返回给调用此函数的函数。
  引用:return句有两形式:reutrn; return expression;……第二形式提供了函数的果。
  笔:以上第一句话说return的两个作用之一:束函数。return的作用之二是提供函数的返回
  return句的两形式,情式一只能用于无返回的函数,情式二可以用于有返回的函数也可用于无返回的函数。
  如果函数有返回,就必用形式二来束,而易的。
  于没有返回的函数,可以不写return句,式的return生在函数的最后一个句完成。也可以用形式一来束,这种用法一般用在函数中,判断某些条件之后就立即束,后面的句不再行。如果用形式二来返回,那express是另一个没有返回的函数。如:
void FuncA();
void FuncB()
{
  return FuncA();
}
  个人认为这种写法不是好习惯,因看起来FuncB有了返回,如果逻辑上有需要,我认为写成以下格式更好:
void FuncB()
{
  FuncA();
  return;
}
  在BASIC中,函数的返回束是由两个不同的实现的。前者是一个函数名赋值句,后者“Exit Function”句。这种设计除了不如C++以外,容易出事。比如在函数开头函数名一个默认值,然后根据某些条件其它特定的Exit。如果写函数不小心漏了某个赋值语句,函数将BUGC++不会这种类型的BUG
  引用:千万不要返回局部象的引用。
  引用:千万不要返回局部象的指
  笔:以上两句是黑体的标题:专门进行了讨论。不过这错误虽重,却不理解。知道了就好了。
  main()是一个很特殊的函数,它的特殊性在有体。引用:返回型不是void的函数必返回一个,但此规则有一个例外的情况:允主函数main没有返回束。……编译器会式地插入返0句。
 
标题:传递的函数与字符串函数
如果将数为实参来用函数,函数接收到的形参其是一个指。数名是可以转换为的,但是数名和指针毕竟不等价。所以,这样传递果是失了数原有的一些特性。最大的失莫sizeof大小的测试看以下程序:
void FuncA(int *temp)
{
  cout << sizeof(temp) << endl;
}
void FuncB(int temp[])
{
  cout << sizeof(temp) << endl;
}
void FuncC(int temp[20])
{
  cout << sizeof(temp) << endl;
}
int main()
{
  int a[10];
  cout << sizeof(a) << endl;
  FuncA(a);
  FuncB(a);
  FuncC(a);
  return 0;
}
  三个函数的写法各有不同,但是果却是一的。其中FuncC的写法尤其容易解。因为编译器不管你传递的是多大的数(甚至不管是不是数),但是函数的写法却在暗示程序员这个数20个成。如果参成20个,果就是没有起到完全的作用,如果参成不到20,那就指越界了。
  避免这样尬,有将指与容量一起入函数:“void FuncD(int temp[], _size_t Size);”,或者传递两个指“void FuncE(int* Begin, int* End);”这样做当然好,不C++有另一种办法可以不用这么,那就是引用传递“void FuncF(int (&temp)[10]);”这样的函数只允int[10]入,大小不符的数或非数的指都无法入。这样就保10的正确性,sizeof都省了。
  C言的字符串理函数大概是有的可以不受此束的函数了。字符串就是字符数,但是在传递字符数组时,可以只而不管大小。因C言中的字符串都是以NULL尾的。前子有人在论坛及字符串和字符指系。回答是:C言的字符串是用字符数存放的,而是借助于字符指。但是,要能这样的操作,有两个条件必须满足:一是所有字符连续放置在以指针开头的内存中、不跳,二是有一个定的束符。int[]之所以不能这样做,是因第二个条件无法
 
标题::函数的引用返回
引用是给变量取一个名,所以引用传递会直接量本身的传递。它的最大好是可以把别处对变量的改保留下来,第二好是它提高了性能:如果函数的返回是一个引用,那,如上文所,它会节约构造、赋值和析构程。但是,函数返回引用往往会来一些意想不到的错误:比如返回临时变量的引用。
//一个错误的函数
int &Max(int i, int j)
{
  return i>j ? i : j;
}
  以上函数的错误在于,ij在函数束后会被放。的引和也将失效。如果用个返回值给别赋值,将会得一个垃圾。VC++.Net以上return示警告。
  那,如果返回一个全局的引用呢?当然是可以的,但是,一来程序设计中不建使用多的全局量,二来全局量即使不返回也可以访问这样做的唯一用途就是把函数做右其它赋值
int m;//全局
int &MaxByGlobal(int i, int j)
{
  return m = i>j ? i : j;
}
int a, b, c;
c = MaxByGlobal(a, b);//
用法一、用返回值赋值
MaxByGlobal(a, b); c = m;//
用法二、不用返回值赋值
  当然,以上MaxByGlobal函数也不是一无是,能用返回赋值程序来更好的可性。只是这样的函数设计本身不被建
  那,函数返回引用用得最多的就是返回形参了。因形参可以用引用传递,引用的形参不是函数内部的局部量,这样做是可取的:
int &MaxByRef(int &i, int &j)
{
  return i>j ? i : j;
}
  上面个函数和上文中的“int Max(int i, int j)”函数如此相似,但是它省去了三次构造、赋值和析构。
  另外一用法就是在的成函数中返回类对象自身了,典型的是“operator +=”函数之
MyClass &MyClass::operator +=(const MyClass &other)
{
  //某些
  return *this;
}
  以上函数返回的是自身的引用。因为类的成函数也可以写成全局函数“MyClass &operator +=(MyClass &Left, const MyClass &right)”,而且在函数的用中实际存在着this传递。所以,以上个函数依然可以看作返回了形参的引用。
  于返回引用的函数,有一个好玩的像。即返回值还可能可以被赋值。如“(a += b) = c;”这样的形式。这种写法明,但是如果函数返回了非const的引用,个表达式的确是合理的。所以,上面的“operator +=”函数要修改一下,将返回“MyClass&”“const MyClass&”
  返回引用并不是处处可用的,正如《引用传递用范》中提到的一:不能用引用来传递临时值。有候我的确要生一个临时对象并返回它,那就不能返回引用。典型的有“operator +”函数:
const MyClass MyClass::operator +(const MyClass &other) const
{
  MyClass Temp;
  //某些
  return Temp;//里只能返回象,因Temp是局部
}
 
标题::函数的非引用返回
函数最多可以返回一个,也可以不返回任何(也有返回void”法)。之所以最多只能返回一个,因只有这样才能在表达式中使用。比如“y=Sin(x);”,如果Sin函数返回多个个表达式就失去了意。之于可以不返回任何经历过BASIC的人应该更能理解。因BASIC中把有返回的程序段叫函数,没有返回的程序段叫做子程序。很然,子程序就是完成一个特定的功能后束的程序段。
  函数的返回没有型限制,可以是内置量,也可以是类对象。无是内置类对象,都有着律。但是,律在C++到来之前很少有人去理会,竟内置型太通,以至于程序根本不去考
  在C代,所有的返回都是局部量。如下列程序:
//
程序一:
int Max(int i, int j)
{
  return i>j ? i : j;
}
//
程序二:
char *StrCpy(char *Target, const char *Source)
{
  char *Temp=Target;
  while(*Source)
  {
    *Temp++ = *Source++;
  }
  return Target;
}
  程序二人一个错觉认为该函数返回的不是函数内部的局部量。错误原因在于没有理解指的本。其程序二和程序一一,返回是形参之一。而形参就是作用域函数内部的局部量。
  理解了返回是局部。因为还有一个很重要的概念没弄清。比如:
int a, b, c;
char d[10], e[10], *f;
//
其它
c = Max(a, b);//
句一
f = StrCpy(d, e);//
句二
  以上注两行句都有同一个问题:如果返回的量作用域限于函数内部,那函数束以后该变量就已不存在了,那么给cf赋值的是什
  CC++有一个机制保以上赋值正常行:在函数束前,先将要返回的局部临时一份到内存(个内存程序知道,也无法知道)。然后将局部销毁,函数正常束。接下来用中的临时变标变赋值赋值结束后再把临时变销毁
  以上程凭空多出一次量构造、制与销毁过程,好在于内置量来这样程所需的性能出并不太多。但是C++到来以后,函数的返回值类型可以是类类型。而类对象的构造、制与销毁可能很复杂、很占用系统资源。于是引用传递再一次发挥了它的威力
 
标题::引用传递用范
经过三篇文章的述,函数的参数传递应该明朗了,经过一番比,似乎引用传递是最秀的一种传递方式。第一、它用法很简单似于值传递,第二、它功能很大,似于指针传递,第三、它很安全,可以避免指针传递带来的危,第四、它效率高,函数中不必要象的建、赋值放。第五、如果不希望参被改,可以使用const形参……
  但是,天下没有这么便宜的午餐!引用传递不是倒能用的。个例子:
void Swap(int& a, int& b)
{
  int temp = a;
  a = b;
  b = temp;
}
  以上函数可以行两个int量的交。但是,很多情况下函数不能用:
int ia = ib = 1;
short sa = sb = 2;
const int cia = cib = 3;
Swap(ia, ib);//
正确
Swap(sa, sb);//
错误short不是int然可以转换为int,但是量不存在
Swap(cia, cib);//
错误两个参数是const
Swap(4, 5);//
常量不是量,似于将short传递给函数
Swap(ia+ib, ia-ib);//
错误,表达式求生的临时值不是
  其中将const参数传递进函数的做法,然看起来有些荒实际上某些候会不做的。某个量在定候并不是const的,但是在用某个函数的候将它作const形参入,而函数内部再Swap()函数量已成了局部的const量。
  以上个特性反用是很有用的。在多人作写程序的候,或者写一个大型程序的候。你不知道某函数是否用const来保参数,但是你想保参数。那,你就在自己写的原函数中将参数保起来。这样,当你用某个没有式指定const引用参数的函数编译器就会报错
void funca(const int& a)
{
  funcb(a);//错误
}
void funcb(int& b)
{
  ...;
}
int t;
funca(t);
以上程序会在注的那行停止编译。因在它用了函数b,而b没有声明参数const然函数b中未必改参数
 
 
标题::形参与参的系之引用传递
C++有了引用传递后,形参的改不影响被判无效。因为传递给函数的并不是一个,而是量自身。在函数中定的形参是局部量,但却是一个引用。个引用的作用域限于函数内部,但是由于它与参就是同一回事,所以它的操作完全等同于对实参的操作。比如你叫黑旋买鱼,或者叫买鱼,去的都是同一个人。
  C++要有引用传递回事?一种说法是只有引用才能达到操作符重的目的,个以后再。但是,撇开这个不,形参是不是引用,直接影响了程序行的效率。前面提到,函数要用参的去初始化形参,初始化的程包含了定一个量、然后一个两个程,如果量并不是内部量,而是一个类对象,那,定一个类对象可能很复杂,而初始化象一会很复杂。而引用只是给对象取一个名,不及定与初始化,离作用域也不用放。
  相比之下,用指针传递可以避免类对象的定、初始化与放。只需要付出指针变量的定、初始化与放的代价。但是,指杀伤力太大。即使是熟的程序,也不能保证绝不出野指,野的代价几乎无一例外是程序崩
  引用也不是吃素的,如果针传递帮你配了一把我家的,那引用传递就是直接把我家的财产都交了你。有,我使用引用传递仅仅了效率,而不希望参被修改,那就要得把形参标记为const,如“UINT GetLength(const CString&)”
  便一句,指针传递也可以这样做。把形参定义为指向const象的指(而不是const),可以降低杀伤力,保护实参所对应的内存。如果是普通的值传递,那有没有const函数外部并不影响。但是,我个人认为,有候加上const也是一件好事。如果程序的逻辑并不需要改参数,而实际写了代,加上const可以让编译器帮我找出BUG,如:
int Max(const int a, const int b)
{
  return a>b?a:b;
}
  VB没有指的概念,却有值传递地址传递两个概念。比如“Function Func(ByRef i As Integer) As Integer”i接受了参后,它的改能影响参。它的实质似于C++中的引用传递
 
 
标题::形参与参的相互
形参的改不影响话说起来巧,但是要完全理解,似乎有几个玄机。
  在我表《函数的定》一文后,有朋友表意,提到了函数程中的入与出,在此首先作个明:我的是《C++ Primer》,而不是《编译原理》,入与出讨论。在讨论的尺度内,我可以这么认为:形参是函数内部的一个局部量,局部量在函数被初始化,而初始化它的值则来自参的。也就是,它的定与初始化似于“int i=3;”。只是被分成两行写了,形参的定写在函数的定中,如:“int ttt(int b)”,初始化写在了用中“cout << ttt(a) << endl;”——参看上一篇文章《形参与参概念》。
  那,在函数中无b,被改的始是形参个局部量,函数,离开这个局部量的作用域,量被放。
  但是,C言的针传递形参能改变实的感,其实这是一个解。于指针传递,函数的形参是一个指传给它的参也应该是指(或者能转为,比如数名、能转换为等)。在函数中,如果改的改就等同于让这个指指向别处),不会影响主函数中的参。但是,由于指针对应着一个内存地址,通它可以改内存的内容。所以,无在函数内部的形参是外部的参,它都可以影响同一内存的。所以,指针传递可以把函数内部的影响到函数外,但是,到函数外的不是形参,而是形参所指的内存。
  就好比我把我家的你配了一把,我手里的匙是参,你手里的匙是形参。你无是把匙折断是磨短,都与我的匙无,但是你用它了我家的却可以把我家洗劫一空。你影响的不是我的匙,而是我的财产
  上文到,C++有了引用传递后,形参的改不影响被判无效。就得提到引用传递的概念了,下文再
本文本的评论有:
简单,用函数的,形参把参克隆了一次,你再怎形参,也与参无.
TNND
就是一个入与出栈过程嘛,你可以去学学汇编.
:
mov cs1,100 //cs1=100;
push cs1 //
cs1;
pop cs2 //
中的内容出栈给cs2;
与另一句等价:
mov cs1,100
mov cs2,cs1
会使用上面的那用法呢?
pushpop占用更少的CPU周期.所以,一般用函数都用入/参数.
 
 
 
标题::形参与参概念
到形参与参,在C++出来之前其简单,就一句:形参的改不影响参。个状直到C++有了引用传递才有改
  要弄清个,首先得弄清形参与参是什么东西。因函数是一段可以重用而不必重写的代次重用当然未必完全相同(不可否有些函数次重用都完全相同),那不同在哪里呢?又怎样产生不同呢?一方法是依靠随机,随机是个好西,不要了,程序都无法控制用的果。第二方法是凭客条件(比如运行时间、机器配置)。但是些函数用很窄,似于“y=Sin(x)”这样的函数就不能这样做。
  那,从“y=sin(x)”的形式看来,能决定函数怎运行的唯一因素就是x了。函数的某次运行是受某一个x的影响并控制的,而下一次运行,会受另一个x的影响。那用函数者就有必要告函数:我要用哪个来控制你,而函数自己有必要保存,直到函数束。
  此,在函数内部建立一个临时的、局部的量,该变量的作用域就是函数内部,该变量的作用时间就是从函数行到行。如果同一函数在同一时间有几个副本在行(这种情况在多线程程序中会出),那是互不相干的,它部的量也是互不相干的。量就叫做形参,全称形式参数。
  形式是跟实际的,另一个参数就是实际参数,叫,在用函数将决定函数内部的形参的参在函数中是否可要取决于两个因素:一是参的作用域,二是有没有被形参覆盖。先第一个因素,如果只C言,那的作用域就是全局与局部两,但是C++作用域一概念,由此第一个因素复杂了。第二个因素本身并不复杂,但是如果没有引起程序的注意,那造成的问题是很难发现的。看下以下程序:
int a;//
全局
int ttt(int a)//
函数的形参也叫a
{
  cout << ++a << endl;
  return a;
}
int main()
{
  a = 3;
  cout << a << endl;
  cout<< ttt(a) << endl;
  cout << a << endl;
  return 0;
}
  程序中有一个全局的a量,但是在ttt()函数中却被另一个a覆盖了,所以,++a没有影响到全局的a,如果把函数定“int ttt(int b)”有不同的
  以上把形参提了这么多,主要目的形参的改不影响。字数不少了,留到下篇文章再吧。(我得我写得不像读书,倒像是教材了。呵呵
 
标题::函数的定
得在哪本上看到,函数的定义为有名称的一段代大概地明了函数的实质:首先、它是一段代,其次、段代可以被重使用而不必重复编写,第三、它是有名字的,在需要重用的候凭名字来用。
  法到了C++复杂了。原因之一是C++支持函数重,也就是了同名函数。编译器在编译时产生不同的函数名,但那必竟是编译器的事,于程序就是同一个函数名。原因之二是C++支持运算符重,可以用一个似于“+”号的运算符来用函数。运算符重着是了配合类对象的运算,因如果没有仅针对内置型,运算符是没必要重的。——试验了一下,自定了一个“int operator +(int i, int j)”函数,果没有通过编译
  于是,到了C++中,函数的概念被修改函数由函数名以及一操作数型唯一地表示,依我看,这样说还来,应该说函数由作用域、函数名以及一操作数型唯一地表示,理由很简单,因在不同的作用域中可以出名称相同、参数型也相同的函数,除非把作用域::函数名合起来看作一个函数名。
  函数函数体没有任何制性要求,哪怕函数体空也可以。不,无是空、一句名,是多句句,花括号一定不可少。在里,包括在花括号内的若干行句不能再视为一个句了——能放句的地方也能放简单语句,而简单语句可以不使用花括号。
  不管你如何看待这组花括号,有一点是肯定的:花括号内部是一个作用域。那,内部定量就只有在内部使用了。就是局部量,在任何函数(包括main())内部定量都是局部——初学者可能以main()内部定量是全局量。
  有一内部量的定与以往的定方式不一,那就是函数的参数。不同之在于:一是它用逗号分隔,二是不允“int i,j”这样的方式定组变量。我想,也正是因所有定用逗号分隔,才造成不允后者的吧,这样来歧——j没有指定型。如果用分号来分隔,那后者的方式也就可以了。C++准的事,我没有能力来为标准出划策,只能妄加猜了。
  函数的返回也是一个型,与量的型一,它可以是内置型,也可以是类类型,可以是引用和指
  引用:在C++准化之前,如果缺少式返回型,函数的返回将被假定int型。
  笔:据我测试,在VC++.NET中,这样做是可以的。照这么说VC++.NET仍然没有按照C++准做?或者VC++.NET迁就了老程序
对本文本的评论有:
函数的参数当然不能使用类似int i,j的方式,因为调用函数的时候,涉及到的不仅仅是定义参数,还有把要处理的变量入栈,调用的函数运行前的第一件事,是把被入栈的变量出栈.
这与int i,j定义变量做的事完全不同,所以,不按定义变量的方式写,也很正常.
如果偷猫兄一定要写得一样,那就自己做一个编译器吧.
 
标题::函数概念
入第七章学
  函数个概念在C/C++是很人的。原因在于,好多C言入门书的第一章第一“C言是由函数成的,初学者学到里,就好像是C的大就被一个麻袋套在上,什也看不了。那些还举了一个例子,然后照着例子个程序是由main()scanf()printf()函数成的……”。我啊,初学者第一天上C,哪里会管什函数不函数的。
  BASIC做得不,倒不是BASICC++好,而是BASIC容易入。在开头节课不必理会这么复杂西,学了“Let“Print就可以简单的算法了。然后提到的函数是包括数学函数在内的内部函数。我在数学里学函数概念,知道“y=Sin(x)”是一个函数,在在BASIC里学到一的函数,自然容易入。等一切都熟悉了,再去学自己写的函数——自定函数,会更加理解程序中的函数概念。
  VB与早期的BASIC相比,使用了事件驱动原理。画完界面就得面函数了,但是VB事件法来回避了。初学者可以不知道“Private Sub Command1_Click()”究竟代表什,只要知道那是控件被单击行的代了。等到后来,学自定函数后,必然会恍然大悟。
  回到C++中,学之初用到的函数的确是成的函数,但是正因为过早地提到了函数概念,致了初学者无所适从。有没有法呢?当然有了,至少《C++ Primer一直到第七章才始提函数二字。
  另外:VB中有函数子程序两个不同的概念,如今子程序又叫,除了使用不同的关键字以外,它的惟一区是有没有返回C将它合并了,都叫函数。其VB里的函数也可以弃返回,只是VB里没有与“void”对应,无法定不返的函数,才不得已出此下策
 
 
标题:trycatchassert
程序是要慢慢成的,比如错误处这种事情,就不是一始就面的。当我们编的程序很小,小到“cin>>i; cout<<i;”这样的程度,错误处理不是我要学的目。但是,一旦用的程序,那,无周到,无精良。意外免的。些意外可能来自程序设计不到位、可能来自用错误操作、可能来自机器与网的不确定因素。
  没有什比追踪错误难过的事了,得有一回我在追踪一个VB程序的错误经过长时间测试,我发现程序在运行中突然生很大的跳:函数ABBC,在C程中,居然会突然跳到A中。后来追查发现,原来A中有一行“On Error Goto”句。一个句,影响了我调试C函数。从那以后,我明白了,除非程序要布了,否则别动错误处理。
  C++VB不一VB用一句“On Error Goto”错误处理后,在函数束之前一直有效(除非式地关闭它)。如果生了异常,理代要根据异常的来分析异常的型。而C++可以选择可能出异常的内容放try后的中。一个函数内部可以有多个try,而try又可以附多个catch理。应该说C++中的异常理更灵活,当然也更容易出。我前生的错误就是在ADO理后只有“catch(_com_error *e)”,但是实际上出的异常却不是“_com_error”的,果仍然抓不往异常。
  异常理和assert系有些以捉摸。一方面它各有各的作用,另一方面它会互相影响。我就曾上面吃过亏:我的程序是在服器上运行的,从来没人会着服器看,所以我的程序不允许弹对话框。我写了比完善的异常理,无么错误,都记录进LOG文件,然后继续运行。但是我却是用DEBUG模式编译的,果异常到来try没起作用,倒是assert起作用了,了个对话框在那儿。件事我的启是:自己是程序的客就可以用DEBUG模式编译
对本文本的评论有:
错误捕捉是很烦人,我的感觉是能在try代码段外解决的错误,就尽量在外头自己解决,尽量少依靠try来处理捕获错误.
在网络编程中,有些错误是无法预知的,比如网络连接断了,数据库当了...好象在这些情况下,用try比较好.
我有一次写的一个服务程序,用户用了一段时间后,经常会异常中止,查来查去查不出原因,后来才发现是ORACLE的日志满了,这个错误显然我在写程序的时候没有想过,丢脸啊...
 
标题:breakcontinuegoto
breakcontinue的使用范一致,两都可以用于循,其中break可以用于switch。功能上也有一定的相似性,break就相当于退学,continue相当于跳break,程序究竟跳到哪儿比好理解。但是continue究竟跳到哪儿去了,初学者可能有些疑惑,不妨就当它跳到了循体最后一句句的后面。
  如果它们处在由多重循switch成的圈圈里,那包括它的最里起作用。于是,想一下子跳出多重循的人可能忘不了goto
  引用:从上世60年代后期始,不主使用goto句。……所有使用goto的程序都可以改写成不用goto
  笔goto是一个很有争句,本建少用或不用它,我个人的习惯决不用。不,至于上世60年代法,我倒是一直不知道。因我自己学BASIC1994年,那候学的是行号的GW-BASICgoto是必用到的句。莫非当学校开设程居然是落后二十年的内容?
  林博士goto另有看法,他错误程序自己造成的,不是goto过错goto至少有一神通,它能从多重循中咻地一下子跳到外面,……就像房子着火了,来不及从楼梯一往下走,可从窗口跳出火坑。……”(《高C++/C程指南》第32
  我写的程序目前没有超越三。从最里往外跳,如果跳一,就break,如果跳两或三,一是这种可能性很小,二是如果真的碰到了,我就用其它条件来控制外是否继续break,自从1997构化的程序设计以来,我的确完全抛弃了goto——VB中的“On Error Goto”除外,出现错误,自然不管在哪一,都我跳进错误处理中。
  goto的目是一个号,号的起名倒有点意思,因为标号只用于goto,所以它的名字可以与任何量名以及其它标识符一而不生重名。以前的程序是行号的,所以就“goto 行号在程序不行号了,但是允在任何地方加号。编译器在碰到它候,大概就是凭其后的冒号来判断个名字不需要检验合法性。那C++中已有的“public:”算不算号呢?
  此,我做了个实验实验内容一是我在的声明里加入了一行“pub:”,二是我在程序段中加入了一行“public:”发现两都都不能通过编译。也就是实验明在义这样的地方不允使用号(也用不着,因它不在任何函数内部,goto是运行的事,与编译,而且goto不允跨函数跳越。),实验明在程序段中的号不允使用保留字
对本文本的评论有:
不主张使用GOTO语句是为了让程序看起来顺眼而己.看:模块化的代码.其实的确没什么大不了的.记住,当你的程序被编译成机器代码以后,里面的跳转全是JMP,相当于GOTO.
 
自从和草莓对骂以来,你就学会了狡辩。
我有跟你讨论机器码吗?
程序设计的风格是为了程序维护,
不是为了编译。
 
标题:whilefor
while中有一个怪事:似于“while (int i = GetInt())”这样句,在条件中定一个量,在for中非常常,也很好理解。但是用在while中却有所不同,如果用在while中,那么每次循都会经历一次建和撤程。——天,是不要这样写吧。幸是在while前面定并初始化量的。
  do-whilewhile有着不一般的系,所以几乎所有的本都是把它放一起的。当年学BASIC,花了不少的功夫去学当型循直到型循。的确,当型和直到型都有存在的必要,因程序的确有种逻辑需要。于是CBASIC以及PASCAL等程序言都提供了。不提供提供,怎用却是程序自己的事。就我个人而言,我是喜用当型循。因当型循可以模出直到型循的效果来。比如以下四段代,它是完全一致的:
//
1
do
{
  循;
  BoolVal = 表达式;
}while (BoolVal);
//
2
BoolVal = 1;//
True
while(BoolVal)
{
  循;
  BoolVal = 表达式;
}
//
3
do
{
  循;
}while (
表达式)
//
4
while(1)
{
  循;
  if (!表达式) break;
}
  for句的序和逻辑是最难讲清的了。如果知道了,就是这么回事。如果不知道,不上半天口舌是不清的。原因在于for包括四个互相关联句,其中三个在“for”后面的括号里,另一个作体存在。BASIC要将for句定义为“For i=M To N Step t”的格式。
  for括号里的三个句是可以省略的,最牛B的省略莫“for (;;)”了。会这样写的人,要彻彻底底地明白了for逻辑的人,要是一点不懂的人。我得,如果要我这样写,我不如写“while(1)”了。
 
 
标题:ifswitch
不愧为经,在if地方能避免教,色,真叫人佩服。
  大体上if要注意的就只有else的配对问题了。如果在else前方有多个没有配if,那就找最近的一个配。如果要改变这种拉郎配,就加上花括号。
  是引用林博士的一句吧:“ifforwhiledo……论执句有多少都要加{}这样可以防止写失(《高C++/C程指南》第16
  if句曾有一个令我疑惑了好久的西:“else if”究竟算什?因BASIC里有“ElseIf”关键词,而C++中所“else if”是两个词组成的。中插了个空格。我都知道,C++句与句之插入若干个(包括0个)空格、TAB、回都是一的,那,如果我把else后插入一个回,不成了另一种结构的if句了?后来我仔地分析一下逻辑关系,才豁然朗:原来是BASIC“ElseIf”了我的理解。C++中用哪方法去理解都没区
  都switchif而出的,但是switch然可以if,却并不是任何候都能使用。使用switch有两个先决因素:一是所有的条件都必编译时常量。也就是如果要在程序运行再决定case后的条件,那是不行的。另一个因素是只能拿出若干个整数来比是否相等,既不能是浮点数,也不能比大于或小于。
  switch最容易出的就是break句了。因按常思路,人们总两个号之句才是应该执行的。从BASIC来的人更加痛苦,因BASIC里不需要似于break这样句来表示束。
  我的做法是,在打程序框架,先把case号和break写了,其余的再去完善。即使逻辑上不需要break句,也要写上“//break;”这样可以提醒自己和团队的伙伴:此并未break,而是的确不需要。
  default是最理直气壮的了。因的确有候并不需要default,但是我的经验是要加上default以及它后面的break,原因同上,提醒自己和伙伴我没有
 
标题:简单语句与
贺进入第6章的学
  简单语句就是只有一句的句,也叫,是由多句成的一个整体。BASIC也有的概念,但是它却是不同的概念:BASIC简单语视为特殊的,而C++块视为特殊的简单语句。个人认为C++句的存在是C++没有“end if”类语句的缺陷。
  BASIC中,ifend if(行if除外)、whilewenddoloop。也就是,有就有尾,所以,BASIC编译器不担心无法确定的大小。C++不同,它的关键字都没有句。没有标记知道它的主体究竟是几行呢?所以,C++只好定:所有构的句体都只能包含一句,而且必包含一句(有且有一句)。话说,如果要多句,你也得做成一句的
  将多行做成一行,就是所了。
  简单语句,空句和空是不能不提的。空句()也是句(),只是它也不干。空句存在的原因,无非也是因C++定了句体必是一句。了,那些构的句体是有且有一句,不仅仅多于一句要写成一句的,反,如果没有任何内容,你也得造一句出来。于是世了。
  以下句就是一个典型的例子:
int s = 0;
for (int i=1,s=0; i<101; s+=i,++i) ;//

  空句的存在C++徒增了度与危性,很多初学者弄不清哪些句要以分号尾,哪些句不要,错误地在for()后面加了个分号,果使循体被取消了循格,而且有可能出死循
 
 
标题:转换
引用:转换也称为强转换
  笔:我得要提转换,得从C格的起。里面可能有我个人的原因。因我个人习惯C格的转换
  在C言中,转换就是用借助一括号同型名和表达式列出来,比如“(int)t”“int(t)”就是把t转为int型。
  引用:因要覆盖通常的转换,所以需式使用转换……式使用转换的另一个原因是:可能存在多种转换时,需要选择特定的转换
  笔:从外文图书译过来的中国图书有个通病,就是言不。本算是翻得非常好的了,依然无法这种影响。上文的意思无非是:我不希望使用默转换规则候,就可以式地定按我的要求转换。如果要个例子,可以拿上文《转换转换》中一个成的例子:
int a = -3;
unsigned b = 3;
if (a == b)//
转换转为unsigned int
if (a == (int)b)//
式指定转换为int
  这种用法更多地用于指针类型的转换。因针类型就是指所指向象的型,而指本身是没有型区的。所以,指向任何型的指可以互相转换。最典型的就是void*和其它型之的互了,比如:“int* p = (int*)malloc(sizeof(int) * MaxSize);”
  有一用法就是在编译器不允许进转换候,比如将const转为const象。如:
const int t = 3;
int* p = (int*)&t;//
本来要写作const int* p = &t;
  这种用法是少用好,理由很简单编译器之所以不允许进转换,就是了保数据,你非要破坏这种安全性自然不好。即使能确信这样做不果,这样做至少是没有良好格的。
  C++为显转换提供了四不同的操作符:static_casedynamic_castconst_castreinterpret_cast。个人认为C格的相比似乎都没有什么进步
  引用:转换关闭或挂起了正常的检查烈建程序避免使用转换,不依赖强转换也能写好很好的C++程序。
 
 
标题:类对象的转换
与算术类型相比,转换复杂。因术转换及到精度的问题,而类对象的转换及到能否转换以及怎样转换问题
  转换就是转换,它会出在你没有注意的地方。参看以下代
class CMyInt
{
public:
  CMyInt();
  CMyInt(int i);
  ~CMyInt();
private:
  int m_i;
};
CMyInt::CMyInt()
{
  m_i = 0;
  cout << "无参数构造(0)" << endl;
}
CMyInt::CMyInt(int i)
{
  m_i = i;
  cout << "从整数构造,值为" << i << endl;
}
CMyInt::~CMyInt()
{
  cout << "析构" << m_i << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
  CMyInt a;
  a = 3;
  return 0;
}
  行以上代发现,程序中有两次构造与两次析构,原因是“a = 3;”赋值表达式要将右转换为型。转换是通过调用构造函数来行的。
  不,以上代只是测试用的,千万不要在实际工作中写这样的代。因为这样做是很不科学的。“a = 3;”这样的表达式,只要CMyInt提供了右值类int赋值操作符重,就可以避免使用构造函数来转换。操作符重如下:
  在public段添加一行:“CMyInt& operator = (const int i);”然后在外部添加以下代
CMyInt& CMyInt::operator = (const int i)
{
  m_i = i;
  cout << "operator =" << i << endl;
  return *this;
}
  加了以上代,同“a = 3;”就不使用转换了,改使用赋值操作。我写下以上段程序的目的只是验证VC++中会有类对象的转换,它与算术类型的转换差不多:生成一个合适的临时对象,参与运算以后再把临时对放掉
标题:函数再
函数是C++提出来的概念,但是在C中却未必没有。比如“1+3”“1.0+3.0”然都是加法,做的却不是同的操作:编译器要因操作数的不同而用不同的加法操作。只是C言中除了内部量可以参与运算以外,没有这么高深的概念。构体也只是内存数据的组织方法,而不整个构体的理。所以,在C编译器明明做了似于重的事情,却可以像雷做好事不留名
  C++展出了,并且予了很高的期望,象也能像内置象一参与一切运算。那,就拿加法运算来编译器如何知道类对象的加法该调用哪一个详细的操作代?于是,即使不出普通函数的重,至少运算符是要重的。
  林博士在《高C++/C程指南》中函数的必要性提了另一个理由:的构造函数名称必名相同,而常要定多个不同的构造函数。那就只好重了。
  于普通程序,我完全可以不用考这么深。重函数至少还带来了另一个好:不用记忆多个不同的函数名了,也不用函数起名而汁了。不书还给出了一个建:并不是任何候都有必要重函数的,有的候不同的函数名可以直来好多信息,用重只是牲了名称中的信息。
 
标题::重函数的概念
引用:出在相同作用域中的两个(可以是两个以上——猫注)函数,如果具有相同的名字而形参表不同,函数。
  本节开头第一句出了重函数的定:重函数必符合两个条件:一是出在相同的作用域中、二是函数名字相同而形参表不同。
  其中第一个条件一般人往往是不去想的,其函数名相同而作用域不同的函数大大存在,比如在MFC中就有。它是完全不相干的函数。
  第二个条件可以详说一下:函数名字相同当然不在下,是函数被称的根源。之于形参表不同,可能表在形参个数不同、可能表在形参型不同、可能表在形参序不同。
  如果要可以不是重函数的情况。
  一、如果既在同一作用域下、名称也相同、形参表也相同,后者被视为前者的重声明。——函数可以重声明,因函数的声明并不生目,但是函数的定不允
  二、如果既在同一作用域下、名称也相同、形参表也相同,但是返回不同,后者被视为错误的声明。函数不可以只凭返回来区分,因为调用函数的候只凭名称和形参来选择函数,而不凭返回。再究其原因,一是因函数的返回可以被弃;二来即使不弃,将返回值赋予另一个量之前没必要检查我需要什么样的返回,而能否赋值也与函数本身无
  三、有些候看起来形参表不同,实际上是完全相同的,本第229页讲了四组这样的例子:
Record lookup(const Account &acct);
Record lookup(const Account &);//
在于有没有形参命名
typedef Phone Telno;
Record lookup(const Phone&);
Record lookup(const Telno&);//
只是给类型取了个
Record lookup(const Phone&, const Name&);
Record lookup(const Phone&, const Name& = "");//
在于形参提供了默认值
Record lookup(Phone);
Record lookup(const Phone);//
在于是否const  
  其中第三可能会生函数的形参个数不同的假像,其可缺省的形参并没有减少形参的个数。第四有点不容易搞清:因有的候可以凭是否const来重,比如引用传递和指针传递
 
标题::文件的组织
一个程序往往由多个源文件成,些代究竟应该放在哪个源文件里、哪些代可以放在同一个源文件里、哪些代必需分放。是一个管理面的问题
  它是管理面的问题,是因为这些代组织往往没有惟一的准。但是它们还是有一定的律的。
  首先,件的维护是一个复杂的系工程。代组织应该有利于维护应该尽量把直接相的内容放在同一文件、不相的内容放在不同的文件里。如果些代码还和疏,那就要分不同的文件来存放了。
  其次,件的代是一个格的组织体系。不同的内容之可能是并列的,也可能有必要的先后系。于是在“#include”候要注意序。
  最后,也是最重要的一点,有些代在同一工程中可以重用(或必重用),有些代在同一个工程中只能出一次。可以重用的有的声明、函数的声明、量的声明等,不可以重用的是体、函数的体、量的定等。那,把可以重用的内容放在h文件中,把不可以重用的放在cpp文件中是一个好法。
  拿的声明和例,如果把一个的所有内容一古放在同一个文件中,将可能出现问题。因在其它用到类实例的地方都必须让类的声明,所以我往往在文件部加个“#include”体也被编译多次,在时产生冲突。
  在前文中曾提到,内函数是惟一允(也是必)在编译时让函数体可的的函数。所以内函数可以放在h文件中。C++规则中有一句正好与此照:在的声明中直接写出的函数被认为是内函数。
  Visual C++给类的文件起默,文件名往往与名一致。如果名由“C”开头文件会是除去开头“C”字以外的其它文字。如“CMyClass”,它的代存放在以下两个文件中:“MyClass.h”“MyClass.cpp”中。原因是VC++议类名以C开头,至于在文件名中不出现开头“C”,可能是出于微习惯
 
标题:的构造函数
引用:构造函数是特殊的成函数。
  笔:构造函数的确是一特殊的成函数。它的特殊性至少表在以下几个方面:一是它的用不用程序操心,只要类对象被建它就会被用,而且它不允被程序员显式地用。二是它是必需的,如果程序员偷懒编译器将自动创简单的构造函数。三是它的名字不用程序多考,直接与名相同。四是它没有返回
  下面详说这几个特性:
  一、它类对象被动调用,象可能有以下方法:程序中用声明量的句直接声明建,或者在程序中用new关键动态创建。方法都可以象,也都可以象数。只要有一个象被建,构造函数就被用一次。
  如果程序式地用构造函数那是不行的。正因如此,构造函数中有一特定的部分叫初始化列表,通它程序可以用基或成的构造函数。必竟设计千差万,如果某个的基或(和)成有多个构造函数,那该类指定用哪一个构造函数,否则类的功能将大打折扣。用构造函数不是程序的事,程序应该管也管不了。初始化列表解决问题而生,所以只有构造函数才有初始化列表,其它函数不能有。
  上面到的大打折扣究竟是怎的折扣呢?如果不能指定基和成用哪一个构造函数,那就只好让编译器去挑了,构造出来的象往往不符合要求,只好用基和成的其它函数,比如赋值函数或其它行参数定的函数——当然,基和成包含这样的函数。这样就浪源。
  二、包含构造函数——确切地是必包含无参数构造函数和拷构造函数——原因是因用是自的。如果两个函数根本就没有,你如何用?所以,C++也不含糊,你要是得写,它就帮你写一个简单的。简单就意味着至少要失一些功能,如果类设计得比较复杂(比如包含指操作)可能引起灾性事故。
  三、函数名与名一致。构造函数的名称是必特殊的,即使个特殊不表在与名相同,也必找到另一个规则实现。因要自动调些函数,你就必须让知道哪些函数是构造函数。
  第四个特性直接改C/C++言的一条规则C定,如果函数没有明指出返回型,那C认为返回int型。C言之所以可以有规则,一是因返回int的函数很多,二是因即使没有返回,也必指明void。当制定规则的人无法料到,C++中居然会出void都不是的返回的函数,void然表示不返回任何,必竟与构造函数的没有返回是两事。于是,C++定:在定或声明函数,没有式指定返回型中不合法的。当然的构造函数除外。
  构造函数的出有它的可行院厝恍浴?尚行允怯捎++包含成函数,既然可以包含普通的成函数,那包含特殊的函数自然也不在下。必然性是由于象往往必须经过特定的初始化。C++到来之前,C言中的数据型只是内置型。于内置象,如果忘了初始化,大不了象失去作用,但是不会致大的问题。比如一个int,无内存如何随机,它的取都不会超int能表达的范行运算也不会生危(溢出不能算危,即使初始化的数据也不能保不溢出,而且溢出只是一种逻辑问题)。但是在的这么简单了,忘了初始化往往将来运行错误。于其次都要考数据的初始化,不如把个初始化写成一的函数,动调用来得既安全又方便
 
 
标题:的成函数
C言中的构体最大的区就是可以函数,而构体只是一个内存。所以,要提就不得不提成函数。
  的成函数与普通函数(全局函数)相比,最根本的区实现的封装性。封装性的第一个表访问权限:都是函数,但是你能访问哪个不能访问哪个却可以定。第二个表是直,通过类(或指)来用函数,人的直就是提供的功能。你好像“Bird.Fly();”一目了然。
  在理解this以前要想底理解成函数是有困的,我就曾以例中保存了函数的副本。要不然,同一个的不同个函数有不同的效果呢?原来,在函数所有的形参之外,有一个不用你操心的参数this,它是一个指的目就是函数的用者。这么就明白了。
  函数形参表后加入const就成了“const函数这样的函数保用者自身不被修改。如CStringGetLength()函数,你只能取它的度,不能修改它的内容或度。加入const的作用倒不是怕用者修改,而是防止写函数的人不小心改象。因百密有一疏,万一在某个不修改数据的函数中改了数据(比如将“==”写成“=”),或者万一用了另一个非const的成函数都将可能引起错误。在写函数前就先加上const可以记编译器来帮你检查
  const加在形参表的后面得有些怪怪的,造成怪怪的原因就是因函数的形参表中没有this,也就没有能用const来修西了。林锐说大概是因其它地方都已被占用了并不是根本原因。
 
标题::内函数
函数应该了改善C言中的宏替的不足而生的吧。因宏替预编译中直接展的,展开过程中将生意想不到的果。典型的有“#define MAX(a, b) (a) > (b) ? (a) : (b)”“result = MAX(i, j)+2;”将被展开为“result = (i) > (j) ? (i) : (j) + 2;”然外面再加一括号可以解决以上问题,但是“result = MAX(i++, j);”被展后将i被自增1了两次。(以上例子摘自林博士的《高C++/C程指南》第66,林叫做边际
  C++用内来取代宏替,大大提高了安全性。然内函数也是编译时的,但是它能行安全检查的成函数(原因是内函数能够处this,宏却不能)。
  引用:内联对编译器来只是一个建编译器可以选择忽略个建
  笔:也就是,有些函数你想内编译器也不一定会采。因函数然减少了函数用的开销,却增加了程序的体
  内函数是唯一允许实体多次被编译的函数。原因是编译器必编译这个函数体,才能在编译函数用的地方行合理地展明在多个CPP文件成的工程中,可能有不止一个CPP文件中要有函数的体。既然这样,就放进头文件吧
本文本的评论有:
得象max()和以前的数越界一的事,都可以归纳为一句,那就是,C提供了大的工具,那些不会使用的人才会出现这种错误.个数越界也管理不好的,是去写武侠小.
比如火药发明了以后,可以用来炸山路什,道因有人用于,就怪个火功能不完善?
是这样的,我们不应该怪C标准不好,
虽然它不能让result = MAX(i++, j);这种问题得到解决,
产生i被自增两次这样的结果,程序员应该自己去避免。
但是,如果标准有进步了,我们倒是因为祝贺它一下。
 
 
标题::局部象与静局部
首先向明了名字的作用域象的生命周期两个概念,不,理解了就行了。前者是空概念:指程序还处在代码阶段的个名字的可,后者是时间概念:指程序运行程中象的存在时间
  函数的形参以及函数内部声明的象都是局部象,它的作用域就是函数内部,但是它的生命周期却未必是函数的程。看起来有点摸不着头脑,原因在于C++的函数中允存在以关键“static”声明的静态对象。
  也就是,静态对象是这样一个象:它的生命周期很,可以跨越函数的用,哪怕函数24用一次,它也是全天候存在的。但是要想访问她,却只有函数正在行的候才行。
  于以上特性,我专门写了两个测试函数,函数途返回局部象的引用或指
int& GetInt()
{
  int t=3;
  return t;//警告
}
int* GetInt2()
{
  int t = 3;
  return &t;//警告
}
  以上两个警告生的原因是函数返回了临时对象的引用或地址。但是如果将t的声明改成“static int t=3;”就不再示警告。
  静局部象似乎为节约统开销做了准。不认为这个特性不应该用。只有确有必要让对象生命周期跨越多次应该把它声明(比如统计函数被用的次数)。否将提高造成BUG的可能性,使高效率的程序成空中楼
标题::默认实
没什偷懒更舒服的了,所以我喜认实参的函数,我写允认实参的函数。
  在形参表中,如果允某些形参具有默认值按从右到左的方向排列。以上C++BASIC是一的,但是C++BASIC有一点区,就是在函数C++从右边开始缺省参,而BASIC却可以任意缺省而不次序(只要有逗号表示那里缺了个西即可)。所以,同样设计函数,C++BASIC要多考一个问题设计带有默认实参的函数,其中部分工作就是排列形参,使最少使用默认实参的表参排在最前,最可能使用默认实参的形参排在最后。
  形参的默认值竟究写在声明中体中?我曾经试过,在某些情况下写在声明中或体中一可行。但是,事上写在体中是错误的做法。只有当函数体和函数用在同一个源文件中,而且函数体在用前被编译时,将形参的默认值写在体中才可通过编译实际这种情况,函数根本就不用声明。
  将默认值写在体中不仅仅是能否通过编译问题还关系到程序设计的理念。一是函数的实现本来就与参数是否有缺省,所以,没有必要缺省在函数的定体中。二是参数的缺省可能会改然修改函数的声明比修改函数的定要方便。(《高C++/C编译指南》第63
  里,本书给了我一个大大的惊:原来默认实参的默认值还可以是任何表达式。以前,我一直是这样写的:“int GetInt(int i=3);”然没人跟我这样说过,但是我始后面的默认值只能是常量。想不到可以是需要求量甚至是更复杂的表达式:
int GetInt(const int i = 3);
int GetInt2(const int j = GetInt());//
居然可以这样
  学了,感C++ Primer》!
 
标题::函数的声明与
注:本中提到了声明两个。我倒是认为将后者改更好。
  函数的体就是实实在在的函数内容,它定了个函数怎样执行,没有什的。那函数么还要有声明呢?
  这样做的目的之一是告诉编译器:然你没有到函数本身,不知道函数是怎样执行的,但是我先告个函数的名称、参数与返回,你就先编译吧。至于个函数究竟干什,等到接的候再
  设计合理的程序,其代存放在不同的文件中,函数的体只能有一个,存放在某一个源文件中。其它源文件中如果要用到个函数,就在个文件中加入函数的声明。
  这样做的目的之二是函数的提供者与使用者往往不是同一个人,甚至不是同一个企。出于种种目的,函数的提供者可能并不想(或不必)使用者知道个函数的具体内容,只要使用者能用就行。这种情况下,函数的提供者只需要提供一个声明使用者即可。——C言的函数就是这样的。
  然而在需要用到函数的文件中加入函数的声明也有好法与笨法。将声明句重写一遍自然,但是这样做有两个明的缺点:一是烦琐、二是不易修改。所以,函数的声明应该放在文件中,哪儿要,就在哪儿包含。就好像我家没有摆许多盆花而是多面子。我在哪儿都能看到花,水却只要一盆。
  个理也适用于C++的声明写进头文件,而体却写程序文件。不同的是,的声明不像函数的声明那只有一句,而是一个完整的
 
 
标题:递归
引用:直接或用自己的函数称为递归函数。
  引用:递归函数必一个止条件,否函数将永远递归下去,意味着函数会一直用自身直到程序耗尽。
  初识递归候,的确有些不容易搞明白。得当的教科书为此画一个,用一来表示要AB、要B又要先C……,用另一表示算好了C就可以算B、算好了B就可以算A……例程序与一个图结合,如此实讲道理,要递归自然稍容易些。
  要写递归函数就得递归的妙用,要写没有错误递归函数悟其数学原理。我倒是这样的函数与数学归纳有些相通之。不同的是,数学归纳是先求界条件,再去往无方向归纳。而递归是从无方向向算的。函数如何行,与我如何写没有必然的系,于是,我在写程序的候也可以先写界条件。这样做可以在程序开头先把可能的问题给排除掉。远递归下去的可能性自然被降低。比如求乘的函数:
//
程序一、上的例子
int factorial(int val)
{
  if (val > 1)
    return factorial(val-1);
  return 1;
}
//
程序二
int factorial2(int val)
{
  if (val <= 1)
    return 1;
  return factorial2(val-1);
}
  程序二的写法与程序一没有区,但可以告自己递归止条件。防止一不小心就写了个
  似乎大多数递归函数都可以用循来解决。方法迁就了不同的象:循用少量的算机源、大量的人力来解决问题递归则用大量的算机源、少量的人力来解决问题。所以,在算机速度和存量都不大的年代,曾有人反对递归
  汉诺问题是只有用递归才可以解决的问题,其只有要求解汉诺塔的移动过程才必递归,如果只要求解移次数,那用循也不成问题
对本文本的评论有:
阶乘的函数写错了.
int factorial(int val)
{
  if (val > 1)
    return val* factorial(val-1);
  return 1;
}
晕,我忘了相乘了,哈哈。
 
标题:return
引用:return句用于束当前正在行的函数,并将控制返回给调用此函数的函数。
  引用:return句有两形式:reutrn; return expression;……第二形式提供了函数的果。
  笔:以上第一句话说return的两个作用之一:束函数。return的作用之二是提供函数的返回
  return句的两形式,情式一只能用于无返回的函数,情式二可以用于有返回的函数也可用于无返回的函数。
  如果函数有返回,就必用形式二来束,而易的。
  于没有返回的函数,可以不写return句,式的return生在函数的最后一个句完成。也可以用形式一来束,这种用法一般用在函数中,判断某些条件之后就立即束,后面的句不再行。如果用形式二来返回,那express是另一个没有返回的函数。如:
void FuncA();
void FuncB()
{
  return FuncA();
}
  个人认为这种写法不是好习惯,因看起来FuncB有了返回,如果逻辑上有需要,我认为写成以下格式更好:
void FuncB()
{
  FuncA();
  return;
}
  在BASIC中,函数的返回束是由两个不同的实现的。前者是一个函数名赋值句,后者“Exit Function”句。这种设计除了不如C++以外,容易出事。比如在函数开头函数名一个默认值,然后根据某些条件其它特定的Exit。如果写函数不小心漏了某个赋值语句,函数将BUGC++不会这种类型的BUG
  引用:千万不要返回局部象的引用。
  引用:千万不要返回局部象的指
  笔:以上两句是黑体的标题:专门进行了讨论。不过这错误虽重,却不理解。知道了就好了。
  main()是一个很特殊的函数,它的特殊性在有体。引用:返回型不是void的函数必返回一个,但此规则有一个例外的情况:允主函数main没有返回束。……编译器会式地插入返0句。
 
标题:传递的函数与字符串函数
如果将数为实参来用函数,函数接收到的形参其是一个指。数名是可以转换为的,但是数名和指针毕竟不等价。所以,这样传递果是失了数原有的一些特性。最大的失莫sizeof大小的测试看以下程序:
void FuncA(int *temp)
{
  cout << sizeof(temp) << endl;
}
void FuncB(int temp[])
{
  cout << sizeof(temp) << endl;
}
void FuncC(int temp[20])
{
  cout << sizeof(temp) << endl;
}
int main()
{
  int a[10];
  cout << sizeof(a) << endl;
  FuncA(a);
  FuncB(a);
  FuncC(a);
  return 0;
}
  三个函数的写法各有不同,但是果却是一的。其中FuncC的写法尤其容易解。因为编译器不管你传递的是多大的数(甚至不管是不是数),但是函数的写法却在暗示程序员这个数20个成。如果参成20个,果就是没有起到完全的作用,如果参成不到20,那就指越界了。
  避免这样尬,有将指与容量一起入函数:“void FuncD(int temp[], _size_t Size);”,或者传递两个指“void FuncE(int* Begin, int* End);”这样做当然好,不C++有另一种办法可以不用这么,那就是引用传递“void FuncF(int (&temp)[10]);”这样的函数只允int[10]入,大小不符的数或非数的指都无法入。这样就保10的正确性,sizeof都省了。
  C言的字符串理函数大概是有的可以不受此束的函数了。字符串就是字符数,但是在传递字符数组时,可以只而不管大小。因C言中的字符串都是以NULL尾的。前子有人在论坛及字符串和字符指系。回答是:C言的字符串是用字符数存放的,而是借助于字符指。但是,要能这样的操作,有两个条件必须满足:一是所有字符连续放置在以指针开头的内存中、不跳,二是有一个定的束符。int[]之所以不能这样做,是因第二个条件无法
 
标题::函数的引用返回
引用是给变量取一个名,所以引用传递会直接量本身的传递。它的最大好是可以把别处对变量的改保留下来,第二好是它提高了性能:如果函数的返回是一个引用,那,如上文所,它会节约构造、赋值和析构程。但是,函数返回引用往往会来一些意想不到的错误:比如返回临时变量的引用。
//一个错误的函数
int &Max(int i, int j)
{
  return i>j ? i : j;
}
  以上函数的错误在于,ij在函数束后会被放。的引和也将失效。如果用个返回值给别赋值,将会得一个垃圾。VC++.Net以上return示警告。
  那,如果返回一个全局的引用呢?当然是可以的,但是,一来程序设计中不建使用多的全局量,二来全局量即使不返回也可以访问这样做的唯一用途就是把函数做右其它赋值
int m;//全局
int &MaxByGlobal(int i, int j)
{
  return m = i>j ? i : j;
}
int a, b, c;
c = MaxByGlobal(a, b);//
用法一、用返回值赋值
MaxByGlobal(a, b); c = m;//
用法二、不用返回值赋值
  当然,以上MaxByGlobal函数也不是一无是,能用返回赋值程序来更好的可性。只是这样的函数设计本身不被建
  那,函数返回引用用得最多的就是返回形参了。因形参可以用引用传递,引用的形参不是函数内部的局部量,这样做是可取的:
int &MaxByRef(int &i, int &j)
{
  return i>j ? i : j;
}
  上面个函数和上文中的“int Max(int i, int j)”函数如此相似,但是它省去了三次构造、赋值和析构。
  另外一用法就是在的成函数中返回类对象自身了,典型的是“operator +=”函数之
MyClass &MyClass::operator +=(const MyClass &other)
{
  //某些
  return *this;
}
  以上函数返回的是自身的引用。因为类的成函数也可以写成全局函数“MyClass &operator +=(MyClass &Left, const MyClass &right)”,而且在函数的用中实际存在着this传递。所以,以上个函数依然可以看作返回了形参的引用。
  于返回引用的函数,有一个好玩的像。即返回值还可能可以被赋值。如“(a += b) = c;”这样的形式。这种写法明,但是如果函数返回了非const的引用,个表达式的确是合理的。所以,上面的“operator +=”函数要修改一下,将返回“MyClass&”“const MyClass&”
  返回引用并不是处处可用的,正如《引用传递用范》中提到的一:不能用引用来传递临时值。有候我的确要生一个临时对象并返回它,那就不能返回引用。典型的有“operator +”函数:
const MyClass MyClass::operator +(const MyClass &other) const
{
  MyClass Temp;
  //某些
  return Temp;//里只能返回象,因Temp是局部
}
 
标题::函数的非引用返回
函数最多可以返回一个,也可以不返回任何(也有返回void”法)。之所以最多只能返回一个,因只有这样才能在表达式中使用。比如“y=Sin(x);”,如果Sin函数返回多个个表达式就失去了意。之于可以不返回任何经历过BASIC的人应该更能理解。因BASIC中把有返回的程序段叫函数,没有返回的程序段叫做子程序。很然,子程序就是完成一个特定的功能后束的程序段。
  函数的返回没有型限制,可以是内置量,也可以是类对象。无是内置类对象,都有着律。但是,律在C++到来之前很少有人去理会,竟内置型太通,以至于程序根本不去考
  在C代,所有的返回都是局部量。如下列程序:
//
程序一:
int Max(int i, int j)
{
  return i>j ? i : j;
}
//
程序二:
char *StrCpy(char *Target, const char *Source)
{
  char *Temp=Target;
  while(*Source)
  {
    *Temp++ = *Source++;
  }
  return Target;
}
  程序二人一个错觉认为该函数返回的不是函数内部的局部量。错误原因在于没有理解指的本。其程序二和程序一一,返回是形参之一。而形参就是作用域函数内部的局部量。
  理解了返回是局部。因为还有一个很重要的概念没弄清。比如:
int a, b, c;
char d[10], e[10], *f;
//
其它
c = Max(a, b);//
句一
f = StrCpy(d, e);//
句二
  以上注两行句都有同一个问题:如果返回的量作用域限于函数内部,那函数束以后该变量就已不存在了,那么给cf赋值的是什
  CC++有一个机制保以上赋值正常行:在函数束前,先将要返回的局部临时一份到内存(个内存程序知道,也无法知道)。然后将局部销毁,函数正常束。接下来用中的临时变标变赋值赋值结束后再把临时变销毁
  以上程凭空多出一次量构造、制与销毁过程,好在于内置量来这样程所需的性能出并不太多。但是C++到来以后,函数的返回值类型可以是类类型。而类对象的构造、制与销毁可能很复杂、很占用系统资源。于是引用传递再一次发挥了它的威力
 
标题::引用传递用范
经过三篇文章的述,函数的参数传递应该明朗了,经过一番比,似乎引用传递是最秀的一种传递方式。第一、它用法很简单似于值传递,第二、它功能很大,似于指针传递,第三、它很安全,可以避免指针传递带来的危,第四、它效率高,函数中不必要象的建、赋值放。第五、如果不希望参被改,可以使用const形参……
  但是,天下没有这么便宜的午餐!引用传递不是倒能用的。个例子:
void Swap(int& a, int& b)
{
  int temp = a;
  a = b;
  b = temp;
}
  以上函数可以行两个int量的交。但是,很多情况下函数不能用:
int ia = ib = 1;
short sa = sb = 2;
const int cia = cib = 3;
Swap(ia, ib);//
正确
Swap(sa, sb);//
错误short不是int然可以转换为int,但是量不存在
Swap(cia, cib);//
错误两个参数是const
Swap(4, 5);//
常量不是量,似于将short传递给函数
Swap(ia+ib, ia-ib);//
错误,表达式求生的临时值不是
  其中将const参数传递进函数的做法,然看起来有些荒实际上某些候会不做的。某个量在定候并不是const的,但是在用某个函数的候将它作const形参入,而函数内部再Swap()函数量已成了局部的const量。
  以上个特性反用是很有用的。在多人作写程序的候,或者写一个大型程序的候。你不知道某函数是否用const来保参数,但是你想保参数。那,你就在自己写的原函数中将参数保起来。这样,当你用某个没有式指定const引用参数的函数编译器就会报错
void funca(const int& a)
{
  funcb(a);//错误
}
void funcb(int& b)
{
  ...;
}
int t;
funca(t);
以上程序会在注的那行停止编译。因在它用了函数b,而b没有声明参数const然函数b中未必改参数
 
 
标题::形参与参的系之引用传递
C++有了引用传递后,形参的改不影响被判无效。因为传递给函数的并不是一个,而是量自身。在函数中定的形参是局部量,但却是一个引用。个引用的作用域限于函数内部,但是由于它与参就是同一回事,所以它的操作完全等同于对实参的操作。比如你叫黑旋买鱼,或者叫买鱼,去的都是同一个人。
  C++要有引用传递回事?一种说法是只有引用才能达到操作符重的目的,个以后再。但是,撇开这个不,形参是不是引用,直接影响了程序行的效率。前面提到,函数要用参的去初始化形参,初始化的程包含了定一个量、然后一个两个程,如果量并不是内部量,而是一个类对象,那,定一个类对象可能很复杂,而初始化象一会很复杂。而引用只是给对象取一个名,不及定与初始化,离作用域也不用放。
  相比之下,用指针传递可以避免类对象的定、初始化与放。只需要付出指针变量的定、初始化与放的代价。但是,指杀伤力太大。即使是熟的程序,也不能保证绝不出野指,野的代价几乎无一例外是程序崩
  引用也不是吃素的,如果针传递帮你配了一把我家的,那引用传递就是直接把我家的财产都交了你。有,我使用引用传递仅仅了效率,而不希望参被修改,那就要得把形参标记为const,如“UINT GetLength(const CString&)”
  便一句,指针传递也可以这样做。把形参定义为指向const象的指(而不是const),可以降低杀伤力,保护实参所对应的内存。如果是普通的值传递,那有没有const函数外部并不影响。但是,我个人认为,有候加上const也是一件好事。如果程序的逻辑并不需要改参数,而实际写了代,加上const可以让编译器帮我找出BUG,如:
int Max(const int a, const int b)
{
  return a>b?a:b;
}
  VB没有指的概念,却有值传递地址传递两个概念。比如“Function Func(ByRef i As Integer) As Integer”i接受了参后,它的改能影响参。它的实质似于C++中的引用传递
 
 
标题::形参与参的相互
形参的改不影响话说起来巧,但是要完全理解,似乎有几个玄机。
  在我表《函数的定》一文后,有朋友表意,提到了函数程中的入与出,在此首先作个明:我的是《C++ Primer》,而不是《编译原理》,入与出讨论。在讨论的尺度内,我可以这么认为:形参是函数内部的一个局部量,局部量在函数被初始化,而初始化它的值则来自参的。也就是,它的定与初始化似于“int i=3;”。只是被分成两行写了,形参的定写在函数的定中,如:“int ttt(int b)”,初始化写在了用中“cout << ttt(a) << endl;”——参看上一篇文章《形参与参概念》。
  那,在函数中无b,被改的始是形参个局部量,函数,离开这个局部量的作用域,量被放。
  但是,C言的针传递形参能改变实的感,其实这是一个解。于指针传递,函数的形参是一个指传给它的参也应该是指(或者能转为,比如数名、能转换为等)。在函数中,如果改的改就等同于让这个指指向别处),不会影响主函数中的参。但是,由于指针对应着一个内存地址,通它可以改内存的内容。所以,无在函数内部的形参是外部的参,它都可以影响同一内存的。所以,指针传递可以把函数内部的影响到函数外,但是,到函数外的不是形参,而是形参所指的内存。
  就好比我把我家的你配了一把,我手里的匙是参,你手里的匙是形参。你无是把匙折断是磨短,都与我的匙无,但是你用它了我家的却可以把我家洗劫一空。你影响的不是我的匙,而是我的财产
  上文到,C++有了引用传递后,形参的改不影响被判无效。就得提到引用传递的概念了,下文再
本文本的评论有:
简单,用函数的,形参把参克隆了一次,你再怎形参,也与参无.
TNND
就是一个入与出栈过程嘛,你可以去学学汇编.
:
mov cs1,100 //cs1=100;
push cs1 //
cs1;
pop cs2 //
中的内容出栈给cs2;
与另一句等价:
mov cs1,100
mov cs2,cs1
会使用上面的那用法呢?
pushpop占用更少的CPU周期.所以,一般用函数都用入/参数.
 
 
 
标题::形参与参概念
到形参与参,在C++出来之前其简单,就一句:形参的改不影响参。个状直到C++有了引用传递才有改
  要弄清个,首先得弄清形参与参是什么东西。因函数是一段可以重用而不必重写的代次重用当然未必完全相同(不可否有些函数次重用都完全相同),那不同在哪里呢?又怎样产生不同呢?一方法是依靠随机,随机是个好西,不要了,程序都无法控制用的果。第二方法是凭客条件(比如运行时间、机器配置)。但是些函数用很窄,似于“y=Sin(x)”这样的函数就不能这样做。
  那,从“y=sin(x)”的形式看来,能决定函数怎运行的唯一因素就是x了。函数的某次运行是受某一个x的影响并控制的,而下一次运行,会受另一个x的影响。那用函数者就有必要告函数:我要用哪个来控制你,而函数自己有必要保存,直到函数束。
  此,在函数内部建立一个临时的、局部的量,该变量的作用域就是函数内部,该变量的作用时间就是从函数行到行。如果同一函数在同一时间有几个副本在行(这种情况在多线程程序中会出),那是互不相干的,它部的量也是互不相干的。量就叫做形参,全称形式参数。
  形式是跟实际的,另一个参数就是实际参数,叫,在用函数将决定函数内部的形参的参在函数中是否可要取决于两个因素:一是参的作用域,二是有没有被形参覆盖。先第一个因素,如果只C言,那的作用域就是全局与局部两,但是C++作用域一概念,由此第一个因素复杂了。第二个因素本身并不复杂,但是如果没有引起程序的注意,那造成的问题是很难发现的。看下以下程序:
int a;//
全局
int ttt(int a)//
函数的形参也叫a
{
  cout << ++a << endl;
  return a;
}
int main()
{
  a = 3;
  cout << a << endl;
  cout<< ttt(a) << endl;
  cout << a << endl;
  return 0;
}
  程序中有一个全局的a量,但是在ttt()函数中却被另一个a覆盖了,所以,++a没有影响到全局的a,如果把函数定“int ttt(int b)”有不同的
  以上把形参提了这么多,主要目的形参的改不影响。字数不少了,留到下篇文章再吧。(我得我写得不像读书,倒像是教材了。呵呵
 
标题::函数的定
得在哪本上看到,函数的定义为有名称的一段代大概地明了函数的实质:首先、它是一段代,其次、段代可以被重使用而不必重复编写,第三、它是有名字的,在需要重用的候凭名字来用。
  法到了C++复杂了。原因之一是C++支持函数重,也就是了同名函数。编译器在编译时产生不同的函数名,但那必竟是编译器的事,于程序就是同一个函数名。原因之二是C++支持运算符重,可以用一个似于“+”号的运算符来用函数。运算符重着是了配合类对象的运算,因如果没有仅针对内置型,运算符是没必要重的。——试验了一下,自定了一个“int operator +(int i, int j)”函数,果没有通过编译
  于是,到了C++中,函数的概念被修改函数由函数名以及一操作数型唯一地表示,依我看,这样说还来,应该说函数由作用域、函数名以及一操作数型唯一地表示,理由很简单,因在不同的作用域中可以出名称相同、参数型也相同的函数,除非把作用域::函数名合起来看作一个函数名。
  函数函数体没有任何制性要求,哪怕函数体空也可以。不,无是空、一句名,是多句句,花括号一定不可少。在里,包括在花括号内的若干行句不能再视为一个句了——能放句的地方也能放简单语句,而简单语句可以不使用花括号。
  不管你如何看待这组花括号,有一点是肯定的:花括号内部是一个作用域。那,内部定量就只有在内部使用了。就是局部量,在任何函数(包括main())内部定量都是局部——初学者可能以main()内部定量是全局量。
  有一内部量的定与以往的定方式不一,那就是函数的参数。不同之在于:一是它用逗号分隔,二是不允“int i,j”这样的方式定组变量。我想,也正是因所有定用逗号分隔,才造成不允后者的吧,这样来歧——j没有指定型。如果用分号来分隔,那后者的方式也就可以了。C++准的事,我没有能力来为标准出划策,只能妄加猜了。
  函数的返回也是一个型,与量的型一,它可以是内置型,也可以是类类型,可以是引用和指
  引用:在C++准化之前,如果缺少式返回型,函数的返回将被假定int型。
  笔:据我测试,在VC++.NET中,这样做是可以的。照这么说VC++.NET仍然没有按照C++准做?或者VC++.NET迁就了老程序
对本文本的评论有:
函数的参数当然不能使用类似int i,j的方式,因为调用函数的时候,涉及到的不仅仅是定义参数,还有把要处理的变量入栈,调用的函数运行前的第一件事,是把被入栈的变量出栈.
这与int i,j定义变量做的事完全不同,所以,不按定义变量的方式写,也很正常.
如果偷猫兄一定要写得一样,那就自己做一个编译器吧.
 
标题::函数概念
入第七章学
  函数个概念在C/C++是很人的。原因在于,好多C言入门书的第一章第一“C言是由函数成的,初学者学到里,就好像是C的大就被一个麻袋套在上,什也看不了。那些还举了一个例子,然后照着例子个程序是由main()scanf()printf()函数成的……”。我啊,初学者第一天上C,哪里会管什函数不函数的。
  BASIC做得不,倒不是BASICC++好,而是BASIC容易入。在开头节课不必理会这么复杂西,学了“Let“Print就可以简单的算法了。然后提到的函数是包括数学函数在内的内部函数。我在数学里学函数概念,知道“y=Sin(x)”是一个函数,在在BASIC里学到一的函数,自然容易入。等一切都熟悉了,再去学自己写的函数——自定函数,会更加理解程序中的函数概念。
  VB与早期的BASIC相比,使用了事件驱动原理。画完界面就得面函数了,但是VB事件法来回避了。初学者可以不知道“Private Sub Command1_Click()”究竟代表什,只要知道那是控件被单击行的代了。等到后来,学自定函数后,必然会恍然大悟。
  回到C++中,学之初用到的函数的确是成的函数,但是正因为过早地提到了函数概念,致了初学者无所适从。有没有法呢?当然有了,至少《C++ Primer一直到第七章才始提函数二字。
  另外:VB中有函数子程序两个不同的概念,如今子程序又叫,除了使用不同的关键字以外,它的惟一区是有没有返回C将它合并了,都叫函数。其VB里的函数也可以弃返回,只是VB里没有与“void”对应,无法定不返的函数,才不得已出此下策
 
 
标题:trycatchassert
程序是要慢慢成的,比如错误处这种事情,就不是一始就面的。当我们编的程序很小,小到“cin>>i; cout<<i;”这样的程度,错误处理不是我要学的目。但是,一旦用的程序,那,无周到,无精良。意外免的。些意外可能来自程序设计不到位、可能来自用错误操作、可能来自机器与网的不确定因素。
  没有什比追踪错误难过的事了,得有一回我在追踪一个VB程序的错误经过长时间测试,我发现程序在运行中突然生很大的跳:函数ABBC,在C程中,居然会突然跳到A中。后来追查发现,原来A中有一行“On Error Goto”句。一个句,影响了我调试C函数。从那以后,我明白了,除非程序要布了,否则别动错误处理。
  C++VB不一VB用一句“On Error Goto”错误处理后,在函数束之前一直有效(除非式地关闭它)。如果生了异常,理代要根据异常的来分析异常的型。而C++可以选择可能出异常的内容放try后的中。一个函数内部可以有多个try,而try又可以附多个catch理。应该说C++中的异常理更灵活,当然也更容易出。我前生的错误就是在ADO理后只有“catch(_com_error *e)”,但是实际上出的异常却不是“_com_error”的,果仍然抓不往异常。
  异常理和assert系有些以捉摸。一方面它各有各的作用,另一方面它会互相影响。我就曾上面吃过亏:我的程序是在服器上运行的,从来没人会着服器看,所以我的程序不允许弹对话框。我写了比完善的异常理,无么错误,都记录进LOG文件,然后继续运行。但是我却是用DEBUG模式编译的,果异常到来try没起作用,倒是assert起作用了,了个对话框在那儿。件事我的启是:自己是程序的客就可以用DEBUG模式编译
对本文本的评论有:
错误捕捉是很烦人,我的感觉是能在try代码段外解决的错误,就尽量在外头自己解决,尽量少依靠try来处理捕获错误.
在网络编程中,有些错误是无法预知的,比如网络连接断了,数据库当了...好象在这些情况下,用try比较好.
我有一次写的一个服务程序,用户用了一段时间后,经常会异常中止,查来查去查不出原因,后来才发现是ORACLE的日志满了,这个错误显然我在写程序的时候没有想过,丢脸啊...
 
标题:breakcontinuegoto
breakcontinue的使用范一致,两都可以用于循,其中break可以用于switch。功能上也有一定的相似性,break就相当于退学,continue相当于跳break,程序究竟跳到哪儿比好理解。但是continue究竟跳到哪儿去了,初学者可能有些疑惑,不妨就当它跳到了循体最后一句句的后面。
  如果它们处在由多重循switch成的圈圈里,那包括它的最里起作用。于是,想一下子跳出多重循的人可能忘不了goto
  引用:从上世60年代后期始,不主使用goto句。……所有使用goto的程序都可以改写成不用goto
  笔goto是一个很有争句,本建少用或不用它,我个人的习惯决不用。不,至于上世60年代法,我倒是一直不知道。因我自己学BASIC1994年,那候学的是行号的GW-BASICgoto是必用到的句。莫非当学校开设程居然是落后二十年的内容?
  林博士goto另有看法,他错误程序自己造成的,不是goto过错goto至少有一神通,它能从多重循中咻地一下子跳到外面,……就像房子着火了,来不及从楼梯一往下走,可从窗口跳出火坑。……”(《高C++/C程指南》第32
  我写的程序目前没有超越三。从最里往外跳,如果跳一,就break,如果跳两或三,一是这种可能性很小,二是如果真的碰到了,我就用其它条件来控制外是否继续break,自从1997构化的程序设计以来,我的确完全抛弃了goto——VB中的“On Error Goto”除外,出现错误,自然不管在哪一,都我跳进错误处理中。
  goto的目是一个号,号的起名倒有点意思,因为标号只用于goto,所以它的名字可以与任何量名以及其它标识符一而不生重名。以前的程序是行号的,所以就“goto 行号在程序不行号了,但是允在任何地方加号。编译器在碰到它候,大概就是凭其后的冒号来判断个名字不需要检验合法性。那C++中已有的“public:”算不算号呢?
  此,我做了个实验实验内容一是我在的声明里加入了一行“pub:”,二是我在程序段中加入了一行“public:”发现两都都不能通过编译。也就是实验明在义这样的地方不允使用号(也用不着,因它不在任何函数内部,goto是运行的事,与编译,而且goto不允跨函数跳越。),实验明在程序段中的号不允使用保留字
对本文本的评论有:
不主张使用GOTO语句是为了让程序看起来顺眼而己.看:模块化的代码.其实的确没什么大不了的.记住,当你的程序被编译成机器代码以后,里面的跳转全是JMP,相当于GOTO.
 
自从和草莓对骂以来,你就学会了狡辩。
我有跟你讨论机器码吗?
程序设计的风格是为了程序维护,
不是为了编译。
 
标题:whilefor
while中有一个怪事:似于“while (int i = GetInt())”这样句,在条件中定一个量,在for中非常常,也很好理解。但是用在while中却有所不同,如果用在while中,那么每次循都会经历一次建和撤程。——天,是不要这样写吧。幸是在while前面定并初始化量的。
  do-whilewhile有着不一般的系,所以几乎所有的本都是把它放一起的。当年学BASIC,花了不少的功夫去学当型循直到型循。的确,当型和直到型都有存在的必要,因程序的确有种逻辑需要。于是CBASIC以及PASCAL等程序言都提供了。不提供提供,怎用却是程序自己的事。就我个人而言,我是喜用当型循。因当型循可以模出直到型循的效果来。比如以下四段代,它是完全一致的:
//
1
do
{
  循;
  BoolVal = 表达式;
}while (BoolVal);
//
2
BoolVal = 1;//
True
while(BoolVal)
{
  循;
  BoolVal = 表达式;
}
//
3
do
{
  循;
}while (
表达式)
//
4
while(1)
{
  循;
  if (!表达式) break;
}
  for句的序和逻辑是最难讲清的了。如果知道了,就是这么回事。如果不知道,不上半天口舌是不清的。原因在于for包括四个互相关联句,其中三个在“for”后面的括号里,另一个作体存在。BASIC要将for句定义为“For i=M To N Step t”的格式。
  for括号里的三个句是可以省略的,最牛B的省略莫“for (;;)”了。会这样写的人,要彻彻底底地明白了for逻辑的人,要是一点不懂的人。我得,如果要我这样写,我不如写“while(1)”了。
 
 
标题:ifswitch
不愧为经,在if地方能避免教,色,真叫人佩服。
  大体上if要注意的就只有else的配对问题了。如果在else前方有多个没有配if,那就找最近的一个配。如果要改变这种拉郎配,就加上花括号。
  是引用林博士的一句吧:“ifforwhiledo……论执句有多少都要加{}这样可以防止写失(《高C++/C程指南》第16
  if句曾有一个令我疑惑了好久的西:“else if”究竟算什?因BASIC里有“ElseIf”关键词,而C++中所“else if”是两个词组成的。中插了个空格。我都知道,C++句与句之插入若干个(包括0个)空格、TAB、回都是一的,那,如果我把else后插入一个回,不成了另一种结构的if句了?后来我仔地分析一下逻辑关系,才豁然朗:原来是BASIC“ElseIf”了我的理解。C++中用哪方法去理解都没区
  都switchif而出的,但是switch然可以if,却并不是任何候都能使用。使用switch有两个先决因素:一是所有的条件都必编译时常量。也就是如果要在程序运行再决定case后的条件,那是不行的。另一个因素是只能拿出若干个整数来比是否相等,既不能是浮点数,也不能比大于或小于。
  switch最容易出的就是break句了。因按常思路,人们总两个号之句才是应该执行的。从BASIC来的人更加痛苦,因BASIC里不需要似于break这样句来表示束。
  我的做法是,在打程序框架,先把case号和break写了,其余的再去完善。即使逻辑上不需要break句,也要写上“//break;”这样可以提醒自己和团队的伙伴:此并未break,而是的确不需要。
  default是最理直气壮的了。因的确有候并不需要default,但是我的经验是要加上default以及它后面的break,原因同上,提醒自己和伙伴我没有
 
标题:简单语句与
贺进入第6章的学
  简单语句就是只有一句的句,也叫,是由多句成的一个整体。BASIC也有的概念,但是它却是不同的概念:BASIC简单语视为特殊的,而C++块视为特殊的简单语句。个人认为C++句的存在是C++没有“end if”类语句的缺陷。
  BASIC中,ifend if(行if除外)、whilewenddoloop。也就是,有就有尾,所以,BASIC编译器不担心无法确定的大小。C++不同,它的关键字都没有句。没有标记知道它的主体究竟是几行呢?所以,C++只好定:所有构的句体都只能包含一句,而且必包含一句(有且有一句)。话说,如果要多句,你也得做成一句的
  将多行做成一行,就是所了。
  简单语句,空句和空是不能不提的。空句()也是句(),只是它也不干。空句存在的原因,无非也是因C++定了句体必是一句。了,那些构的句体是有且有一句,不仅仅多于一句要写成一句的,反,如果没有任何内容,你也得造一句出来。于是世了。
  以下句就是一个典型的例子:
int s = 0;
for (int i=1,s=0; i<101; s+=i,++i) ;//

  空句的存在C++徒增了度与危性,很多初学者弄不清哪些句要以分号尾,哪些句不要,错误地在for()后面加了个分号,果使循体被取消了循格,而且有可能出死循
 
 
标题:转换
引用:转换也称为强转换
  笔:我得要提转换,得从C格的起。里面可能有我个人的原因。因我个人习惯C格的转换
  在C言中,转换就是用借助一括号同型名和表达式列出来,比如“(int)t”“int(t)”就是把t转为int型。
  引用:因要覆盖通常的转换,所以需式使用转换……式使用转换的另一个原因是:可能存在多种转换时,需要选择特定的转换
  笔:从外文图书译过来的中国图书有个通病,就是言不。本算是翻得非常好的了,依然无法这种影响。上文的意思无非是:我不希望使用默转换规则候,就可以式地定按我的要求转换。如果要个例子,可以拿上文《转换转换》中一个成的例子:
int a = -3;
unsigned b = 3;
if (a == b)//
转换转为unsigned int
if (a == (int)b)//
式指定转换为int
  这种用法更多地用于指针类型的转换。因针类型就是指所指向象的型,而指本身是没有型区的。所以,指向任何型的指可以互相转换。最典型的就是void*和其它型之的互了,比如:“int* p = (int*)malloc(sizeof(int) * MaxSize);”
  有一用法就是在编译器不允许进转换候,比如将const转为const象。如:
const int t = 3;
int* p = (int*)&t;//
本来要写作const int* p = &t;
  这种用法是少用好,理由很简单编译器之所以不允许进转换,就是了保数据,你非要破坏这种安全性自然不好。即使能确信这样做不果,这样做至少是没有良好格的。
  C++为显转换提供了四不同的操作符:static_casedynamic_castconst_castreinterpret_cast。个人认为C格的相比似乎都没有什么进步
  引用:转换关闭或挂起了正常的检查烈建程序避免使用转换,不依赖强转换也能写好很好的C++程序。
 
 
标题:类对象的转换
与算术类型相比,转换复杂。因术转换及到精度的问题,而类对象的转换及到能否转换以及怎样转换问题
  转换就是转换,它会出在你没有注意的地方。参看以下代
class CMyInt
{
public:
  CMyInt();
  CMyInt(int i);
  ~CMyInt();
private:
  int m_i;
};
CMyInt::CMyInt()
{
  m_i = 0;
  cout << "无参数构造(0)" << endl;
}
CMyInt::CMyInt(int i)
{
  m_i = i;
  cout << "从整数构造,值为" << i << endl;
}
CMyInt::~CMyInt()
{
  cout << "析构" << m_i << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
  CMyInt a;
  a = 3;
  return 0;
}
  行以上代发现,程序中有两次构造与两次析构,原因是“a = 3;”赋值表达式要将右转换为型。转换是通过调用构造函数来行的。
  不,以上代只是测试用的,千万不要在实际工作中写这样的代。因为这样做是很不科学的。“a = 3;”这样的表达式,只要CMyInt提供了右值类int赋值操作符重,就可以避免使用构造函数来转换。操作符重如下:
  在public段添加一行:“CMyInt& operator = (const int i);”然后在外部添加以下代
CMyInt& CMyInt::operator = (const int i)
{
  m_i = i;
  cout << "operator =" << i << endl;
  return *this;
}
  加了以上代,同“a = 3;”就不使用转换了,改使用赋值操作。我写下以上段程序的目的只是验证VC++中会有类对象的转换,它与算术类型的转换差不多:生成一个合适的临时对象,参与运算以后再把临时对放掉
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值