Introduction to C++ Programming
-
C++的注释
- 单行注释是 //(两个斜杠)
- 多行注释是 /* */
-
在任何一段代码开始之前都用注释表明代码的作用是一个很好的习惯
-
每个C++语句都必须以分号结尾 , 预处理指令除外
-
变量名不能以数字开头,最好不要以下划线开头,因为下划线开头的变量名常常被编译器使用,避免使用下划线开头的以防止编译器混淆
-
在声明变量的时候,前后用换行突出变量的声明是一个好的编程习惯
-
在每个操作数和操作符之间用一个空格隔开是一个好的编程习惯
-
Relational operators( >, <, >=, <=) 的优先级大于Equality oprators( ==, !=)的优先级
-
=是从右往左运算的,所以x=y=0的顺序是先把0赋值给y,然后把0赋值给x
-
cin 会读取用户的输入,遇到第一个white space就结束
- 所以如果是cin >> nameOfCourse, 用户输入的是"CS101 C++", nameOfCourse得到的值只有“CS101", 剩下来的会被后续的输入操作使用(不需要再次输入了)
int main() { //测试,如果用户用cin输入含有空格的字符串 string input; string input2; cout << "please input first" <<"\n" ; cin >> input; cout << "the first input is : " << input<< "\n"; cout << "please input sec"<< "\n"; cin >> input2 ; cout << "the second input is : " << input2; return 0; }
- 如果第一次输入就含有white space,第二次就不再需要输入,直接用第一次读到的whitespace后面的字符串
-
所以如果要读取含有white space 的字符串,用getline, 它会读取包含空格的字符串,直到遇见换行符,并会舍弃换行符
类
- 始终使用set和get函数来访问和更改class的成员变量是一个好的编程习惯(便于维护和减少错误)
- class的成员变量最好应该为private
函数
- 最好不要使用 float 和 double 来处理钱的问题
- 参数强制:强制类型转化:也许调用的函数声明的是需要一个double类型的参数,但是你传给它的是一个int类型的,这个函数也会正确工作
- 小的可以转化成大的,大的也可以转化成小的(精度会丢失)
- 如:一个用int做参数的square函数,square(4.5)得到的是16而不是20.25
- 小的可以转化成大的,大的也可以转化成小的(精度会丢失)
- 函数在调用之前必须要先定义(使用函数原型,不然编译时错误,报错找不到标识符)
- 用static声明的局部变量还是只可以局部访问的,尽管它会一直保留它的值,直到程序结束
- 外部变量和内部变量同名,外部变量会被内部块所隐藏
- 引用参数是一个变量别名,声明是通过在对应变量的类型后面加一个&,如: int& ref;
- 用引用参数作变量,被调用函数可以通过这个引用变量访问和修改调用函数中的对应值
- 在同一个函数内,引用变量可以当作对应参数的别名
- 引用参数如果声明出来了就必须要被赋值初始化(除非引用参数对应的参数是常量,否则引用参数必须是左值0
- 用的时候可以把int&看作int用
int count=0;
int& ref=count;
ref++;是让count++
-
默认参数:
- 默认参数必须要是函数的参数列表里最右边的参数
- 如果不是最右边的参数,则这个参数右边的所有参数都会被忽略,使用默认值
- 默认值必须在参数名称第一次出现时被指定(也就是函数原型中)
#include <iostream> using namespace std; int boxVolume( int length =1 , int width = 1, int height = 1); int main(){ cout<<boxVolume()<<endl; cout<<boxVolume(10)<<endl; cout<<boxVolume(10,5)<<endl; cout<<boxVolume(10,5,5)<<endl; } ```
- 默认参数必须要是函数的参数列表里最右边的参数
-
一元范围解析操作符
- 如果在同一个范围内,有一个全局变量和一个局部变量重名,使用*一元范围运算解析操作符 :: *可以访问全局变量(如果变量不重名则不需要)
int number = 7; int main(){ double number = 7; cout<<number<<endl <<::number<<endl;
- 总是使用一元范围解析操作符来访问全局变量是一个好的编程习惯
-
函数重载
- 函数的名字相同但是函数的签名不同,就是函数重载
int square( int x ){
return x*x;
}
doble suqare( double x ){
return x*x;
}
- 编译器如何区分出函数重载时用哪一个函数?
- 编译器只会使用变量列表来区分
- 利用函数的签名,编码参数的个数、类型、顺序来确定
- 函数的签名指的是:函数的名称,函数参数的类型和个数、顺序
- 注意:不可以函数的签名相同,而返回变量的类型不同
- 注意:函数重载和默认参数函数可能发生混淆,要当心
- 如果函数重载所作的工作都一样,使用templates会更加简洁和方便
- 只定义一个函数template就等于定义了一整个系列的重载函数(差别就是参数类型)
- 函数模板由template关键词开始
- 后面跟一个尖括号<>
- 尖括号里面是template参数列表
- 每个参数由关键词typename或class(在这里它们是同义词)开头,后面跟一个正式的类型变量(一个占位符,如:T)(用于指定基本类型或用户自定义类型的占位符)
- 一个函数模板就跟寻常的函数一样定义,但是会使用正式的类型变量(也就是像T这样的占位符)代替实际的数据类型
template < typename T >
T max( T value1 , T value2 , T value3 ){
T max = value1;
if( value2 > max )
max = value2;
if( value3 > max )
max = value3;
return max;
}
这里函数模板声明了一个正式的类型变量T作为实际参数类型的占位符,(注意在template变量列表中的一个正式的类型变量只可以作为一种实际类型变量的占位符。
在上一例中,当编译器检测到对这个函数的调用时,传给这个函数的变量的类型就会替换掉所有的占位符T。在这一例中,所有的变量都必须有同一种类型的变量(因为本例只声明了一种正式的类型变量)
由此可见,Function Templates实际上是一种代码产生的方式
-
局部变量如果不初始化,它的值不会被隐性地初始化为0,而是-86464646这样地数字
- static 变量不会这样,就算不初始化为0,也会隐性初始化
-
初始化数组的时候
- 数组的大小必须用常量来进行声明,不可以使用变量,即使那个变量已经被赋值
- 使用const变量来声明一个大小的数组让程序更具有可延展性(只需要修改const变量一处而不需要修改多处)
- const 变量必须在声明的那一条语句中初始化
- 这样就不行
- C++里面传递数组传递的是引用,也就是说,被调用的函数可以直接修改调用函数中的原数组
- 传递的时数组a,这个a实际上是数组第一个元素的地址
- 而且C++的内置数组不知道自己的大小,把数组作为参数时,一定也要同时传入这个数组的大小
- 这样就不行
-
基础:C++程序设计 第二版 钱能
-
《 C++ Primer 》
-
提升:《Effectice C++》
-
《More Effective C++》
-
《Effective Modern C++》
-
用多维数组做参数时,第一维的大小可以不用,但是之后的每一维的大小都需要
以助于定位元素 -
C++的switch只能包含整形或者枚举类型,不可以是double这些
-
C++ 的数组名是数组第一个元素的起始地址。所以
-
-
-
-
注意区分上面两个
-
- -
对于字符串来说,字符串的名字其实是字符串第一个元素的地址,编译器会识别出这是一个字符串指针,从而当使用这个字符串名字来取它的值时,会一直从这个起始地址开始读,一直读到\0
-
要得到字符串的值, 不需要对字符类型的指针解除引用,因为对 char * 解除引用之后就变成了char, 得到的就是一个字符而不是字符串了
-
inline是基于source code的复用,如果要在 .h文件里面使用inline, 必须要在.h文件里面写全函数,不能只写一个函数原型