学习目标:

  • 了解C++的发展历程
  • 了解C++的新特性
  • 掌握C++的新数据类型、新的术语与技术手段
  • 掌握基本的C++编程方法

C++程序

C++程序的编译与执行
C++源代码为.cpp文件,其编辑、编译及运行过程和C语言基本一样,分为编辑、编译、链接和执行4个步骤。
image.png
C++程序的格式与构成

  1. //changedata.cpp
  2. #include <iostream> //包含输入/输出头文件
  3. using namespace std; //使用标准命名空间
  4. void ChangeData(int* a, int* b); //函数原型声明
  5. int main()
  6. {
  7. int x,y;
  8. cout<<"Please input two numbers:\n"; //提示输入两个数
  9. cin>>x; //从键盘输入两个数到x和y
  10. cin>>y;
  11. cout<<"x="<<x<<",y="<<y<<endl; //输出x和y的值并换行
  12. ChangeData(&x,&y); //调用子函数来交换x和y的值
  13. cout<<"The result of changing are: \n";
  14. cout<<"x="<<x<<",y="<<y<<endl; //输出交换后的x和y的值并换行
  15. return 0;
  16. }
  17. void ChangeData(int* a, int* b) //定义函数ChangeData的原型
  18. {
  19. int temp;
  20. temp=*a;
  21. *a=*b;
  22. *b=temp;
  23. }

使用数组——>抽象、封装——->使用结构体———>操作、私有————>使用类

  1. struct Student{ //声明一个表示学生的结构体类型
  2. long lNum; //学号
  3. char sName[12]; //姓名
  4. float fGrade; //成绩
  5. };
  6. class OurClass{ //声明一个班级类
  7. private:
  8. char cName[20]; //定义班级名称
  9. Student stu[N]; //定义N个学生
  10. public:
  11. void Input(); //输入学生信息
  12. void Print(); //输出学生信息
  13. void Sort(); //按学生成绩进行排序
  14. };

C++的一些新特性

1、注释

① 注释符“//”只注释“//”后面的内容,且只注释当前行的内容,不可跨行进行。若要注释多行,可在每行开头添加“//”。例如://changedata.cpp//get the sum of x and y
② “/”和“/”可以注释多行内容,即可以跨行注释,但必须成对出现。

2.新的数据类型

C++在C语言的数据类型基础上又增加了一种新的数据类型,即布尔型(bool),为逻辑型变量,取值范围为true/false,存储大小为1字节。
例如:
bool b;
b=true; //区别于
b=“true”if(b) //等价于
if(b==true)
cout<<”OK”;
注意:bool型变量取值不是字符串“true”和“false”

3.灵活的变量说明

C语言中,局部变量必须集中在可执行语句前声明,而C++可以灵活地声明在程序中的任意位置,允许变量声明与可执行语句在程序中交替出现,但都需要“先定义后使用”。
例如:
int i;
i=100;
int j=90;
j++;
int k=i+j;

4.作用域运算符

在C++或C语言编辑环境中,如果有两个同名变量,即全局变量和局部变量,则局部变量在其作用域内具有优先权。
[例2-4] 作用域运算符实例1。
int T=10;
int main(){
int T;

T=5; //此处修改的是局部变量T的值,而不是全局变量T …
return 0;
}

在局部变量作用域内修改全局变量的值,则使用作用域运算符“::”

  1. int T=10;
  2. int main(){
  3. int T;
  4. T=5; //修改局部变量T的值
  5. ::T=10; //修改全局变量T的值
  6. return 0;
  7. }
  8. C++中,“::”的作用有以下三种:
  9. 1、全局作用域运算符(::名称);
  10. 2、类作用域运算符(类::类成员名);
  11. 3、命名空间作用域运算符(命名空间::名称)。
  12. 关于后两种的使用方法将在后续章节讲解。

5.命名空间

命名空间就是一种将程序库名称封装起来的方法。命名空间是C++为解决变量、函数名和类名等标识符的命名冲突服务的,它将变量等标识符定义在一个不同名的命名空间中。
定义格式如下:
namespace 命名空间标识符
{
成员的声明;
}

#include <iostream>
using namespace std; //使用C++标准命名空间
namespace A {
    char user_name[]="namespace A";
    void showname(){
        cout<<user_name<<endl;
    }
}
namespace B{
    char user_name[]="namespace B";
    void showname(){
        cout<<user_name<<endl;
    }
}

int main(){
    A::showname();    
//用命名空间限制符访问showname()
    B::showname();    
//用命名空间限制符访问showname()
//用命名空间限制符访问变量user_name
    strcpy(A::user_name,"good");    
    A::showname();
    return 0;
}
使用using namespace指令时就可以不用加命名空间名称。这个指令会告诉编译器,
后续的代码将使用指定的命名空间中的名称。例如,在例2-6中就可以进行如下应用
#include <iostream>
using namespace std;    
namespace  A {
    char user_name[]="namespace A";
    void showname(){
        cout<<user_name<<endl;
    }
}
namespace B{
    char user_name[]="namespace B";
    void showname(){
        cout<<user_name<<endl;
    }
}
using namespace A;
int main(){
    showname();            
//访问A中的showname()
    B::showname();            
//访问B中的showname()
//用命名空间限制符访问变量user_name
    strcpy(user_name,"good");    
//访问A中的user_name
    showname();            
//访问A中的showname()
    return 0;
}
namespace  A {
    int a;
    namespace B{
         int a;
    }
}
int main(){
    …
    A::a=1;        
    //为命名空间A中的a赋值1
    …
    A::B::a=2;        
    //为命名空间A中的命名空间B的a赋值2
    …
    return 0;
}

6.新的输入/出

C语言中的输入/输出函数scanf()/printf() 经常因为数据类型和所使用的控制符问题而产生错误,且编译器却检查不出问题。
例如:
int i;
float f;
scanf(“%f %d”, &i,&f);
printf(“%f %d”,i,f);
此时,scanf()和printf()所使用的格式控制符与输入/输出的变量类型不一致,但该错误编译器并没有查出。
因此,C++中使用了更加便捷、安全的I/O(输入/输出)操作。
上面的代码可以改为:
int i;
float f;
cin>>i>>f;
cout<使用I/O操作cin/cout需要包含头文件iostream.h。(后期版本里,C++标准程序库的所有标识符都被定义在一个名为std的namespace中)

#include <iostream>
using namespace std;
int main(){
    int x;
    float f;
    char str[20];
    cin>>x>>f;
    cin>>str;
    cout<<"x="<<x<<endl;        
    cout<<"y="<<y<<endl;
    cout<<str;
    return 0;
}

7.头文件

C++中,头文件可告诉编译器库中哪些是可用的,头文件是存放接口规范的唯一地方,是库的开发者与用户之间的合约。

在C++中文件分为.h头文件和.cpp文件。
1、把“只声明”的代码放入.h头文件中。
2、把“实现”部分代码放入.cpp文件中。
//MyTest.h //头文件            
class A{//类A的声明部分
   int x;
   …
   void test();
   …
};
int fun(); //全局函数fun()的声明部分

//MyTest.cpp            
//类A的实现部分 
void A::test(){
   …
}
int fun(){//全局函数fun()的实现部分
    …
    return 0;
}
int main(){//主函数
    A a;
    …
    return 0;
}

8.引用

1)引用的概念

引用被认为是某个变量或对象的别名
格式为:类型名& 引用名 = 被引用的对象名称;
例如:
int x;
int& y = x;
引用就像给原来的对象起了一个“绰号”,访问引用时,实际访问的就是被引用的那个存储单元。

#include <iostream>
using namespace std;
int main(){
    int i=0;
    int& j=i;
    cout<<"&i="<<&i<<",&j="<<&j<<endl;
    cout<<"i="<<i<<",j="<<j<<endl;
    i++;
    cout<<"i="<<i<<",j="<<j<<endl;
    j++;
    cout<<"i="<<i<<",j="<<j<<endl;
    return 0;
}
运行结果:
&i=004FFB78,&j=004FFB78
i=0,j=0
i=1,j=1
i=2,j=2

引用(&)使用规则如下。
① 当引用被创建时,它必须被初始化(指针则可以在任何时候被初始化)。
② 一旦一个引用被初始化为指向一个对象时,它就不能被改变为对另一个对象的引用(指针则可以在任何时候指向另一个对象)。
③ 没有NULL引用。它必须确保引用是和一个合法的存储单元关联的。当定义一个引用时,必须被初始化指向一个存在的对象,也可以这样写:
int n;
int& m=n;
//int &j; //错误,没有初始化
为引用再提供一个引用也是合法的
例如:
int x=5;
int& y=x;
int& z=y;
【注意】
使用引用时应注意如下问题:
① 不能建立引用数组,例如:
int iData[5];
//int& icData[5]=iData; //错误
② 不能建立引用的引用,例如:
int i;
//int&& j=i; //错误

2)引用与指针

引用与指针有着本质的区别,指针通过变量的地址可间接访问变量,而引用通过变量的别名可直接访问变量。

3)引用与函数 — 引用作为函数参数、引用作为函数返回值

  • 采用引用的主要用途之一就是做函数的参数使用
  • 当函数的返回值为引用方式时,需要特别注意的是,不要返回一个不存在的或已经销毁的变量的引用
    int& tcite2()
    {
      int m = 2;
      //return m;      //错误,调用完函数tcite2()后,临时对象m将被释放,返回值为一个空引用
      static int x = 5;
      return x;
    }
    int* tpointer(int *p)
    {
      (*p)++;
      return p;
    }
    int& tcite(int &c)
    {
      c++;
      return c;
    }
    int main()
    {
      int i;
      tpointer(&i);
      tcite(i);
      return 0;
    }