一
OO思想:每个对象都是一个完整的独立的个体,由相关的属性和行为组合与外界分隔
OO思想的特点:1封装 把对象的属性和方法结合成一个独立的系统单位,并尽可能隐藏内部细节
2抽象 对一类公共问题进行统一描述的过程
3继承 子类对象拥有与其基类相同的全部属性和方法
4多态 在基类定义的属性和行为被子类继承后可以具有不同的数据类型或者表现行为等特性
二
考察程序:数组求和
1 #include<iostream> 2 using namespace std; 3 4 int add(int array[],int n); 5 6 int main() 7 { 8 int a[] = {0,1,2,3,4,5,6,7,8,9}; 9 int size = sizeof(a) / sizeof (a[0]); 10 cout<<"a:"<<sizeof(a)<<endl; 11 cout<<"sum:"<<add(a,size)<<endl; 12 return 0; 13 } 14 15 int add(int array[],int n) 16 { 17 cout<<"array:"<<sizeof(array)<<endl; 18 int sum = 0; 19 for(int i = 0;i < n;i++) 20 { 21 sum += array[i]; 22 } 23 return sum; 24 }
运行结果:
这里的运行结果说明当数组名作为实参传递给形参后,数组名就变为指针指向数组的首地址,而在sizeof(a)中数组名仍为求整个数组的大小,什么时候数组名为整个数组,什么时候代表首地址,参见:数组与指针
于是可以对add函数改写为:
1 int add(int *p,int n) 2 { 3 int sum = 0; 4 for(int i = 0;i < n;i++) 5 { 6 sum += *(p++); 7 } 8 return sum; 9 }
三
考察程序:求一串带有空格的整数和
1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 int sum = 0; 7 int i; 8 while(cin>>i) 9 { 10 sum += i; 11 while(cin.peek() == ' ') 12 cin.get(); 13 if(cin.peek() == ' ') 14 break; 15 } 16 cout<<"sum:"<<sum<<endl; 17 return 0; 18 }
运行结果:
涉及到的几个问题有:
1.cin如何检查输入:跳过空白(空格,换行,制表),直到遇到非空白符,读取字符。即读取从非空白字符开始,到与目标类型不匹配的第一个字符之间的全部内容。若输入与预期内容不匹配,返回false。程序中当输入3.3时,读取到. ,检查为false,跳出循环。
2.cin.peek():peek()函数返回输入中的下一个字符,但不抽取输入流中的字符。仅查看,不抽取。
更多关于输入输出,参见:C++输入与输出
四
考察程序:读文件 写文件
1 #include <iostream> 2 #include <fstream> 3 4 using namespace std; 5 6 int main() 7 { 8 ifstream in("e:\test.txt"); 9 10 if(!in) 11 { 12 cerr<<"can not open the file"<<endl; 13 return 0; 14 } 15 16 char x; 17 while( in>>x ) 18 cout<<x; 19 20 return 0; 21 }
1 #include <iostream> 2 #include <fstream> 3 4 using namespace std; 5 6 int main() 7 { 8 ofstream out("e:\test.txt"); 9 10 if(!out.is_open()) 11 { 12 cerr<<"can not open the file"<<endl; 13 return 0; 14 } 15 16 for(int i = 0;i < 100;i++) 17 out<<i; 18 19 return 0; 20 }
涉及到的几个问题有:
1.读文件用ifstream,写文件用ofstream。读写文件可以用fstream,以上三个类都#include<fstream>中
2.打开文件用out方法,out方法可以接受两个参数,第二个参数为文件打开的模式,文件路径要用“”。
3.检查文件是否打开可以直接判断对象,也可以使用is_open()方法,c++ primer plus推荐第二种(P689),检测到的打开错误更具体(如不适合的文件模式)。
4.用cerr输出错误信息显得更职业,这个流没有缓冲(cout输出是有缓冲的)
未尽事宜参见:C++文件读写
六
考察函数重载(这里仅是参数个数不同)
1 #include <iostream> 2 3 using namespace std; 4 5 int calc(int); 6 int calc(int,int); 7 int calc(int,int,int); 8 9 int main() 10 { 11 cout<<"输入:"<<endl; 12 int x,y,z; 13 cin>>x>>y>>z; 14 cout<<calc(x)<<endl; 15 cout<<calc(x,y)<<endl; 16 cout<<calc(x,y,z)<<endl; 17 18 return 0; 19 } 20 21 int calc(int a) 22 { 23 return a*a; 24 } 25 26 int calc(int a,int b) 27 { 28 return a*b; 29 } 30 31 int calc(int a,int b,int c) 32 { 33 return a+b+c; 34 }
涉及到的几个问题有:
1.仅当函数基本上执行相同任务,但使用不同形式的数据时才应采用重载
2.重载要求函数的特征标(函数的参数列表)不同,不同的含义是参数类型不同,或者是参数个数不同,这与变量名的命名是无关的
3.不能通过返回值不同来重载函数,因为函数调用时不需要返回值,编译器无法知道调用的哪个函数
九
1.一定要牢记一个事实:指针所保存的是内存中的一个地址,它并不是指向的数据的值本身。因此务必确保指针对应一个已经存在的变量或者一块已经分配的内存——不要出现野指针
2.*有两种用途,一是创建指针: int *p = &a; 另外是解引用 *p = 123;
3.c++允许多个指针指向同一个地址
4.void *则为“无类型指针”,可以指向任何数据类型。对一个无类型指针进行解引用前必须先将他转换为一个适当的数据类型。
1 int * pint; 2 void *pvoid; 3 pvoid = pint; /* 不过不能 pint= pvoid; */
如果要将pvoid赋给其他类型指针,则需要强制类型转换如:pint= (int *)pvoid;
在ANSIC标准中,不允许对void指针进行算术运算如pvoid++或pvoid+=1等,而在GNU中则允许
十
1. 以下两句做同样的事情
int *ptr1 = &myArray[0];
int *ptr2 = myArray; 数组名相当于数组第一个元素的指针
2. 数组指针变量存放的是地址,++是按照指向的数组的类型去递增的 +sizeof(类型);特别要注意不能对数组名进行类似++或--这样的运算,但是可以进行算术运算(因为常量是无法进行自加自减,但是可以进行算术运算)。事实上数组名并不是指针,也不是指针常量,只不过很多书里为了方便理解把数组名当成一个指针常量,正确理解是数组名只是一个符号而已,具体详见:数组与指针
3. 函数模版,注意字符串数组的赋值,另外可见数组名可以作为形参传递给指针变量,指针变量是可以进行自加运算的
1 #include <iostream> 2 3 using namespace std; 4 5 template<class T> 6 7 void print(T *i, T *j) 8 { 9 while( i != j) 10 { 11 cout<<*i; 12 i++; 13 } 14 } 15 16 int main() 17 { 18 int num[6] = {1,2,3,4,5,6}; 19 char chatter[6] = {'h','e','l','l','o','