- 输入
- cin
- cin.get();
- cin.sync();
- 简单的格式控制
- 动态内存分配
- 内联函数
- 函数重载
- 函数的缺省参数
- 类和对象起步
- 使用类的成员变量和成员函数
- 构造函数
- 复制构造函数
- 类型转换构造函数
- 析构函数
当一次键盘输入结束时(按下回车)会将输入的数据(包括空白字符,换行符)存入输入缓冲区,当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。
cin忽略开头的所有空白字符 (空格,换行符,制表符等)
读取直至再次遇到空白字符 (空白字符不会读取)
测试:
char a[10],b[10];
char c,d;
cin>>a>>b>>c>>d;
cout<
输入:空格空格空格45空格空格空格换行空格空格空格98换行空格空格15
输出:45///98///1///5
cin.get();
可接收单个字符,包括换行 空格等。
对字符数组:
char c[10],d;
cin.get(c,n);
当输入的字符足够长时,
只会读取n-1个字符,放到 c 里。当n=10时,c[10]里是' ',c是字符串。 当n=11时,读取10个字符放到 c 里,此时c[10]不再是' '
当n>11,仍然是读取 n-1 个字符,但只会将前10个字符放到 c里,余下的虽被读取,但不赋给任何变量
当输入的字符长度小于n-1时,将其全部读取。回车符不会读取 之后如果再有一条cin.get(d); 会将回车符读到
C++中cin、cin.get()、cin.getline()、getline()、gets()
cin.sync();
清空输入缓冲区
再次使用 cin 去读取 数据时,它就只能等待从键盘输入了,因为此时 输入缓冲区为 空。
简单的格式控制
先包含#include
int main(){
cout<要输出的字段长度时,才会起作用,默认以空格填充,可以用setfill来设置其他填充符号
//setprecision()是设置有效数字位数,舍去的时候是四舍五入
// ends 是空格
int main( void ){
const double value = 12.3456789;
cout<<"第一:"<
动态内存分配
二者等价
int *p=new int; // new int 返回 int *类型,动态分配出 sizeof(int)字节的空间,将起始地址 赋给 p。
int *p=(int*)malloc(sizeof(int));
进行释放
delete p;
二者等价
int *p=new int[20]; // new int[20] 也是返回 int *类型
int *p=(int*)malloc(sizeof(int)*20);
进行释放
delete []p;
内联函数
在函数定义前面 加 inline 关键字
调用函数的语句是有时间开销的,为了减少函数调用的开销,引入内联函数。
在对内联函数进行调用时,是将整个函数的代码插入到调用语句处,而不会产生调用函数的语句,提高运行效率。
inline int max(int a,int b){
return a>b? a:b;
}
函数重载
几个函数名字一样 参数个数/参数类型 不同
函数重载 使得函数命名 变得简单
编译器 根据 实参的个数 和 类型 来判断 应该调用 哪个函数
函数的缺省参数
定义函数的时候可以让 最右边的连续若干个参数有缺省值。
void func(int x,int y=2;int z=3){
...
}
类和对象起步
结构化的程序,在规模庞大时,变得难以理解,难以扩充,难以查错,难以重用。
一个类:成员变量 成员函数。
一个类的成员函数在内存里只有一份,被所有对象所共用。对象只包含成员变量,不包含成员函数。
对象所占用的内存空间等于所有成员变量的大小之和。
每个对象有各自的存储空间。彼此不会影响。
使用类的成员变量和成员函数
class A{
};
A a1,a2;
a1.w=5;
a2.Init();
A *p1=&a1;
A *p2=&a2;
p1->w=5;
p2->Init();
访问范围关键字:
private:私有成员,只可以被 成员函数 友元函数 访问
public:公有成员,可在任何地方访问
protected:保护成员,成员函数 友元函数 子类的成员函数可以访问当前对象的
没加的话,默认是 private
class Employee{
private:
char szName[30];
public:
int salary;
void setName(char *name);
void getName(char *name);
void averageSalary(Employee e1,Employee e2);
};
void Employee::setName(char *name){
strcpy(szName,name);
}
void Employee::getName(char *name){
strcpy(name,szName);
}
void Employee::averageSalary(Employee e1,Employee e2){
cout<
私有的成员变量和成员函数 只能在成员函数里进行访问。
设置私有成员的机制,叫隐藏。
目的是强制对成员变量的访问一定要通过成员函数进行。
构造函数
名字与类名相同,可以有参数,不能有返回值
作用:只要有对象生成,就会调用构造函数进行初始化。
如果定义类时没写构造函数,编译器会生成一个默认的无参数的构造函数(不做任何操作)
对象生成时,构造函数自动被调用。 一个类可以有多个构造函数。
class Complex{
private:
double real,imag;
public:
//构造函数 不设 返回值类型
Complex(double r,double i=0){
real=r;
imag=i;
}
};
//Complex *c1=new Complex; //Error ,没有提供构造函数的参数
Complex *c1=new Complex(3); // OK
//Complex c2; // Error, 没有提供构造函数的参数
Complex c2(2); // OK
构造函数在对象数组里如何起作用:
class Test{
public:
Test(int n){
cout<<"采用了第一种构造函数"<
复制构造函数
只有一个参数,参数是对同类对象的引用
class Complex{
Complex(const Complex &c){
}
};
如果没有定义复制构造函数,编译器生成默认的复制构造函数。
复制构造函数起作用的三种情况:
1.用一个对象 去初始化同类的另一个对象
Complex c2(c1);
Complex c2=c1; // 初始化语句
注意 如果是 Complex c1,c2; c1.n=5;
c2=c1; // 赋值语句 并不会调用复制构造函数
2.函数有一个参数是类A的对象时,该函数被调用时,类A的复制构造函数 将被调用
void Func(A a1){
}
int main(){
A a2;
Func(a2);
}
3.函数的返回值是类A的对象时,函数返回时,A的复制构造函数被调用
对于参数是对象的函数,调用时会引发调用复制构造函数,时间效率比较大
可以考虑采用常量引用参数,不会引发复制构造函数,如:
void func(Complex obj){
}
改成
void func(const Complex &obj){
// 函数中 任何 试图改变 obj的值的语句都将是非法的。
}
类型转换构造函数
不是复制构造函数,且只有一个参数的构造函数。
如果没有写类型转换构造函数,编译器是不会自动生成的。下面的 c1=9; 也会报错,因为类型不匹配。
如果写的有,就会将 9作为参数,自动进行调用,生成一个临时对象,赋给 c1。
class Complex{
public:
double real,imag;
Complex(double r,double i):real(r),imag(i){
}
Complex(int i):real(i),imag(0){ // 类型转换构造函数
}
};
int main(){
Complex c1(12,13); // 进入了第一个构造函数 初始化
Complex c2=12; // 进入了 类型转换构造函数,执行的是初始化
c1=9; // 进入了类型转换构造函数,9为参数,生成一个临时对象赋给了 c1
cout<
析构函数
名字与类名相同(前面多一个 ~),无参数,无返回值,一个类只有一个析构函数
在对象消亡时自动被调用
class Ctest{
public:
// 析构函数
~Ctest(){
cout<<"析构函数被调用"<
全局对象在main函数执行之前就会初始化,全局对象初始化就会引发构造函数,如果构造函数里有输出,在main还没有执行的时候,就会有输出。



