C++ 的初步认识:
1. 在 C++ 中 一般在主函数 main 前面用 int来定义,表示返回值为整形,
如果程序正常执行,这返回值为 0; 否则返回值为非零,一般为-1;
2. 在 C++ 中,一般使用 cout , cin 表示输出和输入;
对于 cout 表示 c 和 out 的组合,表示输出流对象, << 为插入运算符,与 cout 配合使用;
本例中的作用是把 双引号 内的字符串插入到输出的队列 cout 中。
除此之外也还可以用 printf 输出;
3. 在 C++ 中,通常不在头文件引用中加入 .h ,而用户自己编译的头文件中可以加.h;
例如: #include<iostream>
4. using namespace std; 表示使用命名空间 std , C++ 中的标准类和库函数都是在 std 里边命名的;
例:输出一行话
int main()
{
cout << "This is a C program. " << endl;
return 0;
}
例:流输入,流输出:
int main()
{
int a,b,sum;
cin >> a >> b;
sum = a + b;
cout << "a + b = " << sum << endl;
return 0;
}
说明:
1 . cin 表示 c 和 in 的组合, cin 是输入流对象; >> 是提取运算符,与cin配合使用;
表示从输入设备中提取数据到输入流 cin 中;
2. endl 是 c++ 的输出时的控制符,作用是换行( end line 的缩写 ),表示本行结束,与\n 作用类似;
注: 输入中间只可用空格, 若用逗号或别的分隔符,则出错;
若要输入空格符,需要用别的函数;
例:比大小:
int main()
{
int max(int a,int b);
int x,y,z;
cin >> x >> y;
z = max(x,y);
cout << "max = " << z << endl;
return 0;
}
int max(int a,int b)
{
int z;
if( a < b)
{
z = b;
}
else
{
z = a;
}
return z;
}
面向对象设计时的例子:
class Student // 声明一个类,类名为 Student
{
private: // 类中的私有部分:
int num; // 私有变量 num
int score; // 私有变量 score
public: // 类中的公用部分;
void setdata() // 公用函数 setdata
{
cin >> num; // 输入 num;
cin >> score; // 输入 score;
}
void display() // 公用函数 display
{
cout << "num = " << num << endl;
cout << "score = " << score << endl;
}
}; // 类的声明结束;
Student stu1,stu2; // 定义两个 Student 类型的变量,称为对象;
int main()
{
stu1.setdata();
stu2.setdata();
stu1.display();
stu2.display();
return 0;
}
说明:
class 为类 类型的声明,可以包含 数据 和 函数,称为 数据成员 和 成员函数;
类中的数据和函数分为两大类: 公有的 public ,私有的 private:
对于被指定公有的数据和函数,即可以被本类成员中的成员函数调用,也可以被类外的语句调用;
对于被指定私有的数据和函数,只能被本类中的成员函数所调用,不能被类外调用( 友元类除外 );
这样可以用来保护数据,只有本类中的成员函数可以调用,防止误调;
对于 class 本身作为一个类型,是不占用实际的存储空间,但是一旦 class 定义了一个 对象,则占用实际空间;
当类外调用成员函数的时候,必须要说明要调用哪个对象的函数,采用 . 成员运算符;
C++ 中的 输入和输出:
1. 采用 cout 输出:
cout 必须和 << 一起使用, 在这里 << 被重载为 插入,而不是 左移的运算符;
可以在一个输出语句中使用多个 << 运算符 将多个输出项插入到输出流 cout 中;
<< 运算符的结合方向为 自左向右, 输出项也是自左向右顺序插入到输出流中;
例:
int main()
{
for(int i = 0; i < 3; i++)
{
cout << "count = " << i << endl;
}
return 0;
}
注 : 1. 每一个输出都要单独用一个 << ;
2. 输出时 可以不用指定数据类型,而系统会自动按数据类型进行输出,这比 printf 要方便;
3. 如果 要指出输出所占的列数,可以用 setw ( iomanip.h头文件 );
例:使用 setw()输出:
int main()
{
int a = 5;
float b = 2.12;
double c = 3.1415;
cout << "a = " << setw(6) << a << endl << "b = " << setw(6) << b << endl;
cout << "c = " << setw(6) << c << endl;
return 0;
}
setw() 表示 为其后面一个输出项 预留五列, 若 输出不足五列, 则右对齐,若 超过五列, 按原长度输出;
2. 采用 cin 输出:
输入流 指 从输入设备 向内存中流动的数据流, >> 把数据送到内存; 称为 提取extracting 或 得到 getting
例:
int main()
{
cout << "Please enter your name and age: " << endl;
char name[10];
int age;
cin >> name;
cin >> age;
cout << "Your name is : " << name << endl;
cout << "Your age is : " << age << endl;
return 0;
}
Const 定义常量:
在C语言中 经常使用 #define 来定义符号常量 #define PI 3.1415, 这样很容易出错;
所以C++ 中采用了 const 类型来定义常变量:
例:
int main()
{
const float PI = 3.1415;
cout << PI << endl;
// PI = 3.15;
return 0;
}
在程序运行期间,此 变量的值是固定的不可改变,但是是作为 一个值不可改变的变量处理;
函数:
1. 函数的原型声明:
在 C++ 中 必须对函数的返回值类型进行声明 ( C 中若返回值为 int可以省略 ) ;
但是可以参数表中可以只包含参数类型,而省略参数参数名:
例:
int main()
{
int x,y,m;
cin >> x >> y;
int max(int ,int );
m = max(x,y);
cout << m << endl;
return 0;
}
int max(int a, int b)
{
if( a < b) return b;
else return a;
}
2. 函数的重载:
对于前面出现的 插入 和 提取符 : << ,>>; 本来是左移和右移 但是 C++ 中又作为别的运算符,
即 允许一个运算符符合不同的场合,称为重载overloading;
例:
在 C 中 若完成一个求取 3个数中的最大数,在类型未知时需要分别写:
int max1(int ,int );
float max2(float ,float);
long max3(long ,long );
而C++ 中允许在同一个作用域之下,用同一个函数名定义多个函数,但这些函数的参数和类型必须有所不同;
这些同名的函数用来实现不同的功能,即重载;
参数类型不同:
int main()
{
int q,w,e;
float a,s,d;
long z,x,c;
int max(int a,int b,int c);
long max(long a,long b,long c);
float max(float a,float b,float c);
cin >> q >> w >> e;
cout << max(q,w,e) << endl;
cin >> a >> s >> d;
cout << max(a,s,d) << endl;
cin >> z >> x >> c;
cout << max(z,x,c) << endl;
return 0;
}
int max(int a,int b,int c)
{
if( b > a)
{
a = b;
}
if( c > a)
{
a = c;
}
return a;
}
long max(long a,long b,long c)
{
if( b > a)
{
a = b;
}
if( c > a)
{
a = c;
}
return a;
}
float max(float a,float b,float c)
{
if( b > a)
{
a = b;
}
if( c > a)
{
a = c;
}
return a;
}
参数个数不同:
int main()
{
int a,b,c;
int max(int ,int ,int );
int max(int ,int );
cin >> a >> b >> c;
cout << max(a,b) << endl;
cout << max(a,b,c) << endl;
return 0;
}
int max(int a,int b,int c)
{
if( b > a)
{
a = b;
}
if( c > a)
{
a = c;
}
return a;
}
int max(int a,int b)
{
if( a>b )
{
return a;
}
else
{
return b;
}
}
系统会 自动根据参数的个数找到与之匹配的函数并调用;
不允许参数个数与类型相同,仅返回值不同!
3. 函数的模板:
即建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代替;
则不必定义多个函数,在调用时系统会根据实参的类型来代替模板中的数据类型;
template<typename T> // 注: 后无分号!!!!
T max(T a,T b,T c)
{
if( b > a)
{
a = b;
}
if( c > a)
{
a = c;
}
return a;
}
int main()
{
int q,w,e;
float a,s,d;
long z,x,c;
cin >> q >> w >> e;
cout << max(q,w,e) << endl;
cin >> a >> s >> d;
cout << max(a,s,d) << endl;
cin >> z >> x >> c;
cout << max(z,x,c) << endl;
return 0;
}
template 的意思是模板,尖括号中 写 typename XXX, 表示一个虚拟的类型名;
要等到函数调用时才知道 T是什么类型;
类型函数也可以不止一个 : template< typename T, typename TT >;
但它只适用于函数的参数个数相同,而类型不同的情况;参数个数不同时不可使用;
4. 有默认参数的函数:
有时需要调用同一个函数时用的都是同一个实参值,此时可以给形参一个默认值;
如:
float area( float r = 6.5 );
则指定 r 的默认值为 6.5 此时调用时可以不必给出实参值:
area();
或者给出别的实参值:
area(3.5);
若有多个形参,可以使每一个参数都有默认值,也可以只对一部分形参指定默认值,另一部分不指定;
如:
float volume( float h, float r = 16.5 ) // 仅仅指定 r的默认值;
可以引用为:
volume(100);
volume(100,15);
实参和形参的结合是从左至右的,因此,指定默认值的参数必须放在形参列表的最右端:
如:
void f1( int a, int b = 5, int c ); // 错误;
void f2( int a, int b, int c = 5 ); // 正确;
注意:
1.
如果函数的定义在函数的调用之前,则应在函数定义中给出默认值;
如果定义在调用之后,则必须在声明中给出默认值,定义中可以不给出;
2.
一个函数不能既作为重载函数,又作为有默认参数的函数,否则在调用时可能分不清;
变量的引用 :reference
变量的引用又称为别名 alias,即为变量起另外一个名字,需要时可以方便、间接的引用;
如:
int a;
int &b = a; // & 不代表取地址;
这就声明了 b 是 a 的引用,即别名。 此后 a和 b表示同一个变量;
在引用时只有声明,没有定义,不单独分配空间,只声明它和原有变量的关系;
在声明一个变量的引用后,在本函数的执行期间,该引用不能再作为其他变量的别名;
如:
int a1,a2;
int &b = a1;
int &b = a2; // 错误;
1. 引用的简单使用:
int main()
{
int x;
int &a = x;
cin >> x;
cout << a << endl;
a = a*a; // 当 X的值变化时,a的值也发生变化;
cout << a << setw(5) << x << endl;
x = x/2;
cout << a << setw(5) <<x << endl;
return 0;
}
关于引用的说明:
1. 引用不是一个单独的数据类型,必须与另外的一个数据联系; 声明的同时必须进行初始化;
如:
int &b = a; // 正确
int &b; // 错
float a;int &b = a; // 错
2. 引用和其所指带的变量 共享同一个内存空间,而系统不为引用另外分配空间;
int main()
{
int a = 3;
int &b = a;
cout << &a << " " << &b << endl;
return 0;
}
3. 同一个变量可以有多个不同的别名:
如:
int a = 3;
int &b = a; // a 的别名;
int &c = b; // c 为 b 的别名,即 a的第二个别名;
4. 一个引用在初始化后, 不可被重新声明为另一个变量的别名;
2. 将引用作为函数参数:
对于 C语言中,函数传值有两种情况:
1. 将变量名作为实参:
此时传递是单向的, 形参值的变化,并不回传给实参,所以实参的值不发生变化;
因为在函数执行时, 形参和实参不是同一个存储单元;
void swap(int a,int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i,j;
cin >> i >> j;
swap(i,j);
cout << i << ',' << j << endl;
return 0;
}
程序执行结束后,取值并不发生变化;
2. 传递变量的指针:
使形参得到一个变量地址,这时形参指针变量指向实参变量单元。
void swap(int *x,int *y)
{
int *temp;
temp = x;
x = y;
y = temp;
}
int main()
{
int i,j;
cin >> i >> j;
swap(i,j);
cout << i << ',' << j << endl;
return 0;
}
3. 传送变量的别名:
把变量的 引用作为形参;
void swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i,j;
cin >> i >> j;
swap(i,j);
cout << i << ',' << j << endl;
return 0;
}
在 swap 的 函数列表声明中 a 和 b 是整形变量的声明;( 注: 此处的 &a不是地址,而是引用 )
而引用型形参的初始化是在函数调用时, 通过虚实结合实现的:
当调用 swap 时,由实参将变量名传给形参,
实际上 实参传给形参的是地址,从而使两个变量拥有相同的地址;
关于引用的进一步说明:
1. 不能建立 void 型的引用;
2. 不能建立引用的数组:
如:
char c[6] = "hello";
char &cp[6] = c;
3. 可以将变量的引用的地址赋给指针,此时指针指向的是原来的变量:
int a = 3;
int &b = a;
int *p = &b; // p 指向 b 的地址,即 a的地址;
4. 不能定义指向引用类型的指针变量,但是可以建立指针变量的引用:
如:
int &*p = &a ; // cuo;
int i = 5;
int *p = &i;
int *&pt = p; // pt 是一个指向int 型变量指针的引用,初始化为 p,即 tp = p;
5. 可以用const 对引用加以限定,不允许改变该引用的值;
int i = 5;
const int &a = i;
a = 3; // 错误;
但是并不阻止改变引用所代表的变量的值:
i = 3; // 正确; i = a = 3;
有时希望保护形参的值不被修改; (链表的表头)
6. 可以用常量或者常量表达式对引用进行初始化,但此时必须使用 const 做声明;
如:
int i = 3;
const &a = i + 3; // 合法;
此时:编译系统首先定义一个临时变量temp 用来存放该表达式的值:
int temp = i + 3;
const &a = temp; 临时变量是内部生成的,用户不可访问;
这种方法可以用来初始化类型不同的变量的引用声明:
如:
double d = 3.14159;
const int &a = d;
此时系统现将 其转化为:
int temp = d; // 将double型的d 转化为 int型 的temp;
const int &a = temp;
但是必须加上const ,如果不加,将失去temp 赋值的一步,出现编译错误;
内置函数:
调用函数的时候,需要一定的时间,如果有的函数需要频繁被调用 ,则累计时间可能会很长;
c++ 提供一种在编译时将所用函数的代码嵌入到主函数中,称为内置函数( 内嵌函数 );
只需在函数首行的左端加上关键字 inline 即可;
inline int max(int a, int b)
{
if(a>b)
{
return a;
}
else
{
return b;
}
}
int main()
{
int x,y;
cin >> x >> y;
cout << max(x,y) << endl;
return 0;
}
内置函数 和用 #define 定义的带参宏定义有一些相似,但是 避免了宏定义可能产生的错误;
注:
使用内置函数 可以节省运行时间,但是却增加了目标程序的长度;
如果 要调用10次函数,则编译时将先后10次将代码复制,插入main函数;
作用域运算符:
float a = 13.5;
int main()
{
int a = 5;
cout << a << endl;
cout << ::a << endl;
return 0;
}
根据规定,局部变量将屏蔽全局变量,此时可以用 作用域运算符 :: ;
此时 ::a 表示全局变量中的 a;
注:不可采用 :: 访问函数中的局部变量!
字符串变量:
C++ 中提供了字符串类型 string 类型来定义字符串变量; ( 实际为一个类 )
1. 定义字符串变量:
字符串变量也必须先定义后使用:
如:
string string1;
string string2 = "China";
注:
此时要包含头文件:
<string> // 不是 <string.h>!!!!
2. 对字符串变量的赋值:
1. 可以使用赋值语句对string类型的变量进行赋值:
string1 = "Canada" ;
而使用字符数组的时候是不可以的:
char str[10];
str = "Canada"; // 错误; strcyp();
2. 也可以用一个字符串变量给另一个字符串变量赋值:(运算符重构!)
string2 = string1;
此时不要求两个字符串的长度一致,也不需要指定长度,它的长度随字符串的改变而改变;
3. 可以对字符串变量某一个字符进行操作:
如:
string word = "Chini";
word[4] = 'a'; // 对序号为4 的字符进行修改;
注:
字符串常量以'\0'结尾( 在字符数组中也是如此 ),但将字符串常量存放到字符串变量中后,
只存放字符串本身,而不存放'\0'!!
3. 对字符串变量的输入输出:
可以在输入输出时采用字符串变量名进行输入输出:
如:
cin >> string1;
cout << string2;
4. 字符串变量的运算:
1. 赋值运算实现复制:
string1 = string2;
2. 加法运算实现连接;
string str1 = "C++";
string str2 = "Language";
str1 = str1 + str2;
3. 关系运算符实现比较;
5. 字符串数组:
也可以用string 定义一个数组:
string name[5] = { "ZK11111","ZK2222","ZK333","ZK44","ZK5", };
此时:
1. 一个字符串数组中可包含多个字符串变量;
2. 并不要求每一个元素具有相同的长度;
3. 字符串数组与字符数组存在着本质上的区别;
4. 每一个字符串元素中仅仅包含字符串本身的字符,而不包含"\0";
注:
实际上,编译系统对每一个字符串变量分配的都是固定的字节数,用来存放的是字符串的地址;
即在字符串变量中存放的是指针;
template<typename TT>
TT max(TT a,TT b,TT c)
{
if(b > a)
{
a = b;
}
if(c > a)
{
a = c;
}
return a;
}
int main()
{
string str1,str2,str3,temp;
cout << "Please Input three strings:" << endl;
cin >> str1 >> str2 >> str3;
cout << max(str1,str2,str3) << endl;
return 0;
}
动态分配和撤销内存运算符:new 和 delete
在C语言中是运用库函数 malloc 和 free 来分配和撤销内存空间的;
但是malloc 必须指定开辟空间的大小 : *p = ( type )malloc( sizeof() );
并且必须在程序中进行强制类型转换;
而在C++ 中增加了new ,delete 来代替:
如:
new int;
new int(100);
new char[10];
float *p = new float(3.14159) // 开辟一个存放实数的空间,并指定初值为3.14159;
1. new 运算符的一般格式为:
new 类型(初值);并返回对应的指针类型;
但是用 new 分配数组空间时不能指定初值;
2. delete 运算符的一般格式:
delete []指针变量; // 注: 此处为指针变量;
如:
delete p;
char *pt = new char[10];
delete[] pt; // 指针变量前加[] 表示对数组空间的操作;
struct Student
{
char name[10];
int num;
char sex;
};
int main()
{
Student *p;
p = new Student;
strcpy(p->name,"ZK");
p->num = 100;
p->sex = 'F';
cout << p->name << ' ' << p->num << ' ' << p->sex << endl;
delete p;
return 0;
}
若由于内存不足等原因无法正常分配空间,则new 会返回一个NULL指针;
用户可以用此来判断是否正确分配;
注: new 和 delete 为运算符, 而malloc 和 free 为函数!