c++是在C语言的基础上发展起来的一门语言,C++是即支持结构化程序编程又支持面向对象程序设计的混合型语言。他一方面提供了对C的兼容性,保持了C的简介、高效,接近汇编语言的特色,另外一方面,C++引入了类、对象的概念,能够进行类的继承和派生,使C++成为一种面向对象的程序设计语言。早期的具备面向对象性能的程序语言存在不少缺点,如创建对象不凡便,与用户交互能力差等。C++克服了这些缺点,实现了真正的可视化编程。用户使用C++时,不用本身一一创建对象,只要在C++提供的框架内添加实现某种功能的代码便可。ios
c++与C语言兼容,C语言中的数据类型、运算符、表达式、函数定义和调用、预处理命令等在C++中都是适用的,还包括语句格式等。C++继承了C的风格和特色,但同时又对C的不足和问题作出了改进,主要包括:c++
(1)增长了一些新的运算符,使得C++应用起来更加方便,如::,new,delete,.*,->等。编程
(2)改进了类型系统,增长了安全性。C语言中类型转换很不严格,而C++规定类型转换大多采用强制转换,函数的说明必须使用原型,还对默认类型作了限制。数组
(3)增长了“引用”概念,是的引用函数参数更加方便。安全
(4)容许函数重载,容许设置默认参数,这些措施提升了编程的灵活性,还减小了冗余性。服务器
(5)引进了内联函数的该概念,提升了程序的效率。框架
(6)对变量说明更加灵活,在知足先定义后使用的前提下,局部变量的定义和声明能够在程序块的任何位置。函数
C++并不是万能药,这里举出一些C++的适用时机。性能
按应用领域来讲,C++适用于开发服务器软件、桌面应用、游戏、实时系统、高性优化
用Visual Studio不能单独编译一个.cpp或者一个.c文件,这些文件必须依赖于某一个项目,所以必须建立一个新项目,下面建立一个控制他应用程序。
点击确认后,即进入了以下界面
再输入程序以下:
1
2
3
4
5
6
7
8
9
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
cout <<
"hello world!\n"
;
return
0;
}
|
#include<iostream>为预处理命令,预处理器包含在编译器中。iostream为C++自带的库文件,它包含标准流cin、cout输入和输出,当程序中须要用到这些输入输出流对象时,要用#include将其包含在程序中。
第二行using namespace std;,该语句是说明程序使用C++标准库的命名空间std。命名空间是ANSI C++引入的能够由用户命名的做用域,用来处理程序中常见的同名冲突。这个再后面会进行讲解。
运行程序,能够获得以下结果:
·运行结果以下:
C++自己没有专门的输入输出语句,C++的输出和输入不是C++自己定义的,而是编译系统提供的I/O库中定义的,是用“流”的方式实现的,使用的是iostream库。
1
|
cout<<表达式1[<<表达式2<<..<<表达式n];
|
该语句功能是:依次输出表达式一、表达式二、...表达式n的值。具体输出内容能够是一个整数、实数、字符及字符串。虽然cout不是C++自己提供的语句,但为了方便,经常由cout和流插入运算符<<实现输出的语句称为输出语句或cout语句。下面是一个实例:
1
2
3
4
5
6
7
8
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
cout <<
"this is a c++ program"
<<endl;
}
|
在执行该语句是,系统先把插入的数据顺序存放在输出缓冲中,直到输出缓冲区满或遇到cout语句中的endl(或'\n',ends,flush)为止。将缓冲去中已有的数据一块儿输出,并清空缓冲区。
endl表示输出一个换行字符,同时刷新流,若是不用endl,还可使用转移字符‘\n'来表示换行。
其中使用cout语句须要注意如下几点:
例如:cout<<"this is a C++ program"<<endl能够写成:
1
2
3
4
|
cout <<
"this "
<<
"a C++"
<<
"program"
<< endl;
|
或者:
1
2
3
4
|
cout <<
"this "
;
cout <<
"a C++"
;
cout <<
"program"
;
cout << endl;
|
cin语句通常格式
1
|
cin>>变量>>[变量>>...>>变量n];
|
该语句功能为:运行程序时从键盘输入变量一、变量二、...变量n的值。
使用该语句须要注意如下几点:
运行程序是,从键盘上输入多个变量,多个值之间用空格、Tab或回车键分开。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// example1.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
char
c1, c2;
int
a;
float
b;
cin >> c1 >> c2 >> a >> b;
}
|
须要注意的是不能用cin语句把空格字符和回车换行符做为字符输入给字符变量,他们将被跳过。若是想将空格字符或者回车换行符输入给字符变量,可使用getchar()函数。
利用格式控制符能够进行格式化的输入和输出。用oct、dec、hex分别将输入或输出的数值换成8进制、10进制及16进制。例如:
1
2
3
|
cout << oct << a << endl;
//输出a的8进制
cout << dec << a << endl;
//输出a的10进制
cout << hex << a << endl;
//输出a的16进制
|
此外,还有不少格式控制符,例如:
ws:输入流的时候删掉空白字符。
ends:输出一个null字符。
endl:输出一个换行字符,同时刷新流。
flush:刷新流。
下面经过一个实例加深了解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// example1.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
char
a[20];
cin >> a;
cout << a << endl;
return
0;
}
|
这里发现,输入aaa bbb输出却只为aaa,这是由于碰见空格后就结束了,后面BB没法读取出来,因此输出的是aaa.
变量的做用与即变量的做用范围。有的变量能够在整个程序或其余程序中使用,有的则只能在局部范围内使用。按做用域范围范围能够将变量分为两种:局部变量和全局变量。
变量的生存期是指变量从生成到被撤销的这段时间。实际上就是变量占用内存的时间。按生存期长短可将变量分为两种:动态变量和静态变量。
变量只能在其生存期里被引用,变量的做用域直接影响变量的生存期。做用域和生存期是从空间和时间的两个不一样的角度来描述变量的特性。
在一个函数内部定义的变量就是局部变量,其做用域只在本函数范围内有效,也就是说只有在本函数内才能使用他们,在此函数以外是不能使用这些变量的,这是由于函数内的变量是保存在栈内的,而全部栈内的内容在函数调用结束后会被清除。因此,局部变量的生存期是从函数被调用的时刻开始到函数返回调用处的时刻(静态变量除外)结束。在使用局部变量时,须要注意如下几点:
int max(int a, int b);//函数声明a、b int max(int x, int y)//函数定义,形参是x、y { cout << x << y << endl;//合法,x、y在函数内有效 cout << a << b << endl;//非法,a、b在函数体中无效。 }
编译时,系统认为函数体中的a\b未经定义。
2.全局变量做用域和生存期
在函数外部作定义说明的变量,称为外部变量。它属于整个源程序文件。这是由于全局变量是保存在堆中的,堆内的数据能够从程序开始运行一直到程序运行结束。其做用域从定义变量的未知开始到源文件结束,或者是有extern说明的其余源文件。全局变量的生存期和程序相同。使用时须要注意如下几点:
1
|
[
extern
] 类型说明符全局变量名1[ =初始值1],...,全局变量名n[ =初始值n];
|
extern 类型说明符 全局变量名1,...,全局变量名n;
在C++中变量除了有数据类型的属性以外,还有存储类别的属性。存储类别指的是数据在内存中的存储方法。存储方法分为静态存储和动态存储两大类。具体包含四种:自动(auto)、静态的(static)、寄存器的(register)和外部的(extern)。
考虑了变量的存储类型后,变量定义的完整形式应为:
1
2
3
4
5
6
|
存储类型说明符 数据类型说明符 变量名1,变量名2,...变量名n;
例如:
auto
char
c1,c2;
register
i;
static
int
a,b;
extern
int
x,y;
|
程序中大多数变量属于自动变量。函数中的局部变量,若是不用关键字static加以声明,编译系统对它们是动态的分配存储空间的。函数的形参和在函数中定义的变量(包括在符合语句中定义的变量)都属于此类。在调用该函数时,系统给形参和函数中定义的变量分配存储空间,数据存储在动态存储区中,在函数调用结束后自动释放这些空间。若是是在复合语句中定义的变量,则在变量定义时分配存储空间,在符合语句结束时自动释放空间。若是在符合语句中定义的变量,则在变量定义时分配存储空间,在复合语句结束时自动释放空间。所以者类局部变量称为自动变量。自动变量用关键字auto做存储类别的声明。
例:
1
2
3
4
|
int
f(
int
a)
//定义f函数,a为形参
{
auto
int
b, c = 3;
//定义b和c为整型的自动变量
}
|
存储类型auto与int的顺序是任意的,并且关键字auto还能够省略,若是不写auto,则系统默认为自动存储模式,它属于动态存储方式。
注意,用auto、register、static声明变量时,是在定义的基础上加上这些关键字,而布恩那个单独使用。
2.静态变量
静态变量在整个程序生命周期内,其地址静止不变。
静态变量的类型说明符是static。静态变量属于静态存储类型,但静态存储类型的变量不必定是静态变量。例如,外部变量虽属于静态存储类型,但不必定是静态变量,必须用static加以定义后才能称为静态外部变量。
全局变量改变为静态变量后会改变它的做用域,限制了它的使用范围。当一个源程序由多个源文件组成时,非静态的全局变量可经过外部变量说明使其在多个文件中都有效。而静态全局变量只在定义该变量的源文件内有效,在同一项目的其余源文件中不能使用。
自动变量能够用static改变为静态自动变量,改变后,其生存周期为整个源程序,可是做用域与自动变量相同。此外须要注意的是,静态局部变量赋字操做只运行一次,此后再调用,再也不进行赋值。
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
int
i;
void
func();
//函数说明
for
(i = 1; i <= 5; i++)
func();
//函数调用
return
0;
}
void
func()
//函数定义
{
static
int
j = 1;
//静态局部变量,其只运行一次。
++j;
cout << j <<
""
;
}
|
能够看到,五次调用函数func,可是赋值给j=1的操做只执行了一次。
3.寄存器变量(register型变量)
通常状况下,变量的值是存放再内存中的,当程序中用到哪个变量的值时,由控制器发出指令将内存中该变量的值送到CPU的运算器中,而寄存器变量存放在CPU的寄存器中,使用时,不须要访问内存,而是直接从寄存器中读写,这样可提升效率。
寄存器变量的说明符为register,属于动态存储类型。只有局部自动变量和形式参数才能够定义为寄存器变量。
4.外部变量
外部变量(即全局变量)是在函数的外部定义的,它的做用域为从变量的定义开始,到本程序文件的末尾。在此做用域内,本文件的各个函数均可以引用全局变量。编译时将全局变量分配到静态存储区。
若是外部变量不在文件的开头定义,其有效的做用范围只限于定义处到文件结束。若是在定义以前想引用该全局变量,则应该在引用以前用关键字extern对该变量作外部变量声明,表示该变量是一个在后面定义的全局变量。有了此声明,就能够从声明处起,合法的引用该全局变量,这种声明称为提早引用声明。若是程序由多个文件组成,在一个文件中定义的外部变量,在另外一个文件中对该外部变量进行声明后,也能够合法的引用该外部变量。
用extern扩展全局变量的做用域,虽然给程序带来了方便,但会使程序的可读性变差,修改不便,使用时要慎重。
在C和C++中使用函数时,包括函数的声明、定义、调用三部分,都要遵照相应的规则。
函数声明就是把函数的名字、函数类型以及形参的个数、类型和顺序通知编译系统,以便在遇到函数调用时,核查调用形式是否与声明相符。
函数声明的通常形式:
1
2
3
|
函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2,...);
函数类型 函数名(参数类型1,参数类型2..);
|
第二种声明是对第一种声明的简化,它省略了参数名,由于函数声明不涉及函数体,因此编译系统不关心参数是什么。
函数定义是指对函数功能的实现,包括指定函数名、函数类型、形参及其类型、函数体等,他是一个完整的、独立的函数单位。
函数定义的通常形式:
1
2
3
4
5
6
|
函数类型 函数名(形式参数表)
{
声明部分;
函数体主体;
return
返回值;
}
|
使用该函数,叫作函数调用,函数调用方式是:
1
|
函数名(实际参数表)
|
只要函数声明出如今函数调用以前,就能够把包含函数体的函数定义移到函数调用的后面。所以,在程序中调用函数由如下两种方式:
1
2
3
4
5
6
7
8
|
方式1:
函数声明;
函数调用;
函数定义;
方式2
函数定义;
函数调用;
|
例如以前的例子,还能够这样写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
void
func()
//函数定义
{
static
int
j = 1;
//静态局部变量,其只运行一次。
++j;
cout << j <<
""
;
}
int
main()
{
int
i;
for
(i = 1; i <= 5; i++)
func();
//函数调用
return
0;
}
|
C++容许给函数形参赋予默认值。所谓默认值就是在调用时,能够没必要给出某些参数的值,编译器会自动把默认值传递给调用语句。对于函数的形参,能够给出默认值,也能够不提供默认值,还能够指对形参的一部分给出默认值。默认值在函数参数较多时是很是有用的。能够只传必需的值。
使用默认参数时,须要注意如下几点:
参数的默认值能够在声明中或定义中设置,但只能在其中一处设置,不容许在两处同时设置。若是函数的定义在函数调用以后,则只能在函数声明中设置默认参数。由于此时若是在定义中设置,编译器不知道哪一个参数设置了默认值。
设置了默认值的参数,函数调用是能够再也不给值,直接读取默认值,也能够不区默认值,从新赋值。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
add(
int
a,
int
b = 5);
//函数声明
int
main()
{
int
a = 1;
int
b = 2;
cout<<add(a, b) << endl;
//函数调用,第二个参数没有取默认值
cout << add(a) << endl;
//函数调用,第二个参数取默认值
return
0;
}
int
add(
int
x,
int
y)
//函数定义
{
int
z;
z = x + y;
return
z;
}
|
输出结果为:
若是一个函数中有多个默认参数,则默认参数应从右到左逐渐定义。即当某个参数是默认参数,那么它后面的参数必须都是默认参数。例如:
1
2
3
|
int
add(
int
a,
int
b,
int
c=1);
//true
int
add(
int
a=1,
int
b=1,
int
c=1);
//true
int
add(
int
a=1,
int
b=1,
int
c);
//false
|
当调用函数时 ,传进去的实参个数必须大于或等于无默认值的形参的个数,匹配参数时是从左至右去匹配。例如,对三个参数都是默认参数的,正确的调用格式为:
1
2
3
|
add()
//三个参数都取默认值1,函数值为3
add(2,3)
//a=2,b=3,c取默认值1,函数值为6
add(3,4,5)
//a、b、c都不取默认值,结果为12
|
在前面的例子中,参数默认值都是常量,实际上,默认值能够是全局变量,甚至是一个函数调用。
例如
1
2
3
|
int
m = 1;
//m为全局变量
int
fun(
int
i = m);
//正确,参数默认值为全局变量m
int
add(
int
x;
int
y = fun());
//正确,add函数的参数默认值为fun()函数值,并且,fun()函数调用使用的是参数默认值。
|
但默认值不能是局部变量,由于默认参数的函数调用是在编译时肯定的。
函数编程过程当中,常常会遇到这种状况,就是须要编写若干个函数,他们的功能类似,可是参数不一样,能够统一给这些函数取一个相同的名字,但设置不一样的参数,编译系统在函数调用时可以将各个函数区分开来。若是两个函数名字相同而且在相同的域中被声明,可是参数表不一样,那么他们就是重载函数。
重载函数必须是参数类型或参数个数不一样。使用重载函数须要注意:
函数重载要求编译器可以惟一的肯定调用一个函数应执行哪一个函数代码,即采用哪一个函数实现。进行函数重载时,要求同名函数在参数个数上不一样,或者参数类型上不一样,不然,将没法进行重载。
例:编写两个重载求和函数,一个计算两个整数的和,一个计算两个浮点型数的和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
add(
int
x,
int
y);
//函数声明
double
add(
double
a,
double
b);
int
main()
{
cout<<add(2, 3) << endl;
//函数调用,第二个参数没有取默认值
cout << add(2.2,3.3) << endl;
//函数调用,第二个参数取默认值
return
0;
}
int
add(
int
x,
int
y)
//函数定义
{
return
x + y;
}
double
add(
double
a,
double
b)
//函数定义
{
return
a + b;
}
|
内联函数是C++引进的新概念,在C语言中没有。内联函数具备通常函数的特性,他与通常函数的不一样之处只在于函数调用的处理。通常函数进行调用时,要将程序执行权转到被调用函数中,执行完被调用函数后才再次返回到调用它的函数中;而内联函数是在编译时直接将内联函数的函数体代码嵌入到调用函数中,因此内联函数被执行时,不涉及到流程的转出和返回,也不涉及到参数传递,提升了执行效率。
内联函数是在函数声明或函数定义是,在函数名前加一个inline。示例以下
1
2
3
4
|
inline
int
add(
int
x,
int
y)
//函数定义
{
return
x + y;
}
|
使用内联函数有如下注意事项:
引用是C++中提供的一个新概念,它与指针密切相关。引用是一个变量的别名,定义引用类型变量,实质上是给一个已定义的变量起一个别名,系统不会为引用类型变量分配内存空间,只是使引用类型变量和其相关联的变量使用同一个内存空间。
定义引用类型变量的通常格式为:
1
2
3
4
5
|
<数据类型> &<引用名>=<变量名>
//&不是取地址符,是引用的标识
或
<数据类型> &<引用名> (变量名)
|
例如:
1
2
|
int
a=3;
int
&ra = a;
|
这里,ra就是一个引用,他是变量a的别名。引用ra和变量a不只值相同,地址也相同。对引用进行的计算,例如:ra=ra+2;实质上是a加上2,a的结果为5.
使用引用的注意事项以下:
下面经过一个实例加深了解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include "stdafx.h"
#include "iostream"
using
namespace
std;
int
main()
{
int
a;
int
&ra = a;
//将ra引用为a
cout <<
"a="
<< a << endl;
cout <<
"ra="
<< ra << endl;
cout <<
"address of a is :"
<< &a << endl;
cout <<
"address of ra is :"
<< &ra << endl;
int
b = 8;
ra = b;
cout <<
"a="
<< a << endl;
cout <<
"b="
<< b << endl;
cout <<
"ra="
<< ra << endl;
cout <<
"address of a is :"
<< &a << endl;
cout <<
"address of b is :"
<< &b << endl;
cout <<
"address of ra is :"
<< &ra << endl;
return
0;
}
|
运行结果:
引用传递是指将引用做为函数参数来实现的函数参数的传递。
通常的,函数形参为通常变量,调用时实参与形参之间参数传递只能是从实参到形参,是单向的。从被调用函数的角度来讲,参数的值只能传入,不能传出,也就是一般的值传递。当用指针做为函数参数,调用时将实参的地址初始化成形参的指针,则能够实现实参和形参的双向传递,即地址传递。
引用传递是指引用做为函数的形参,当调用函数是,对应的形参就是相应实参的别名。在调用函数内对形参的修改就是对实参的修改;在调用函数外对实参的修改,当进入被调用函数内时,相应的形参就是已经修改的实参,实现了参数的双向传递。
例:利用自定义函数交换两个变量的值,要求用引用做为函数形参。
下面程序中自定义函数的形参为引用。