Error[8]: Undefined offset: 742, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

本文目录

前言

  最近要完成一个WinSock编程的大作业,由于要求太简单,因此想要做一个窗口界面出来,于是想到两年前小学期学得很烂的C++及.NET,便把之前的课件翻出来重新学了一遍,同时想着写一篇博客记录一下。

参考链接

  以下参考链接来自使用过程中遇到的一些问题查询的结果,会按照序号来命名,文中有对应标注。

一、概述

  把课件整体学了一遍之后,发现老师课件的思路非常清晰明确且非常具有逻辑性,因此本博客也打算按照当时老师的思路来行文。首先大致介绍C++的一些特性,然后再重点介绍面向对象编程中的一些重点概念,要求读者具有C语言基础。最后再简单介绍开发工具VS2005的一些使用技巧。

二、C++初步

  众所周知,C++语言的诞生就是基于C语言的,或者说C++是一个更好的C,同时也兼容C,其中最大的区别可能就是C++引入了类的机制,最初的C++也被称为“带类的C”(C language with class),之后才正式改名为C++。

  这里需要注意的是,C++问世之后,并不是说C语言就停滞发展了,二者在之后的时间中都在不断发展,在不断更新标准,其发展历程可以参考这篇文章,讲得非常详细。因此个人建议不必纠结它们中的某个细节是怎么发展更新的,只需要知道目前最新的版本即可

  本博客中根据老师课件的表述,应该是以C++98标准来展开讲述,而且使用的工具——VS 2005也只支持这个标准,虽然版本有点老,但是个人认为对入门C++还是足够了的,因为基本的一些概念在之后的版本更新中也没有太多变化。

附:VS,GCC个版本与C++标准的对应关系

0. 从C到C++

  C++(C plus plus)是C语言的超集,完全兼容C语言,它保持了C的简洁、高效和接近汇编语言等特点,同时对C的类型系统进行了改革和扩充,当然最为重要的还是它支持面向对象的方法编程(C++不是一个纯正的面向对象的语言)。因此在概念上不同于C,应按C++的方式来理解使用它。下面将从以下十个方面来讲述C++与C语言中不同之处,方面读者快速建立印象。

1. 文件扩展名

  为了使得编译器能够区分是C语言还是C++语言,C++语言体系规定用 “.cpp” (意即 C Plus Plus)作为C++语言源文件的扩展名以区别于C语言用的 “.c” 文件扩展名。
  但是C++中头文件的扩展名仍然为 “.h” 。因此Arduino中调用的库一般都是一个.h文件配一个.cpp文件。

为什么还要强调文件扩展名呢?
可能对于目前一些高版本的编译器来说其实没什么差别,但是对于嵌入式等硬件差别还是存在的,不能随便写扩展名。

2. 名字空间

  名字空间的概念是C++独有的,它相当于一个更加灵活的文件域,一般也叫作用域。首先来看一个基础的C++程序:

#include 
using namespace std;

int main()
{
	int i = 3;
	cout << "i = " <<i<<endl;
	return 0;
}

其中的namespace关键词就是用来说明名字空间,std相当于一个标准的命名空间,里面有cout等C++基本的函数,因此在程序的开头要以using namespace std;来声明使用这个命名空间,这样就能使用其内部的函数或变量了。

  注意:在使用using namespace std;时,#include 后面是没有.h的。

  那能不能自定义一个名字空间呢?
  答案是肯定的。如果想自定义一个名字空间,可以用关键词namespace来定义,和定义一个类差不多。

namespace  ns1
{
     float a,b,c;
     void fun1(){……}
}

这样相当于给一些变量和函数限定的范围,因此使用的时候,需要使用作用域符::来表示使用的变量所在的名字空间。举个例子:

namespace  ns1
{
	int  i=10;
}
namespace  ns2
{
	int  i=20;
}

#include      
using namespace  std;

int main( )
{
	int  i=3;
	cout<<"i="<<i<<endl;  //默认作用域中的i变量
	cout <<"i="<< ns1::i<<endl;//ns1作用域中的i变量
	cout <<"i="<< ns2::i<<endl;//ns2作用域中的i变量
	return 0;
}

  通过上面这个例子,我们还可以总结出名字空间的两种用法:①使用using;②使用作用域符::。显然,如果涉及的函数或变量较少,可以使用作用域符;如果需要频繁使用到某名字空间的变量或函数,则可以使用using一个程序里面可以使用多个using,但其作用域中不能有冲突的变量或函数

  对于有结构体和类的概念的同学可能会问:这个和类有什么区别呢?
  确实是一个好问题,经过查找资料找到一篇相对完整的教程【链接】,里面对名字空间有详细的讲述,这其中,我认为和类相比最为不一样的就是名字空间是开放的,可以在使用过程中增添内容。看个例子。

#include 
using namespace std;

namespace A {
    int a = 100;
    int b = 200;
}
//将c添加到已有的命名空间A中
namespace A {
    int c = 300;
}
void test04()
{
    cout<<"A中a = "<<A::a<<endl;//100
    cout<<"A中c = "<<A::c<<endl;//200
}
3. 作用域与作用域符

  在上一节名字空间中,我们对作用域有了一定的概念,但其实这个概念还可以扩展到局部变量和全局变量的范围。
  通常情况下,如果全局变量与局部变量同名,那么局部变量在其作用域内拥有较高的优先级。
  在C++中,提供一个作用域运算符::,它能指定所需要的作用域。来看个例子。

#include    
using namespace std;
float a=2.4;          // 全局变量
void main()
{
	int a=8;          // 局部变量
  	cout<<a<<endl;
  	cout<<::a<<endl;  // ::a表示全局作用域中的变量a
} 

  需要注意的是,作用域符不能访问函数中的局部变量!

4. 输入输出


  其中,<<在C语言中是移位运算符,而这里用来表示输出流,这属于是运算符重载,具体看后面的教程。

  这里对于初学者来说可能会混记的是cin和cout运算符分不清,这里我给的建议是,把cin和cout想象成一个端口,然后在cin和cout左边是输入输出终端,右边是需要输入输出的内容,这样根据数据的流向就能判断符号的方向了。

5. 变量类型与定义

  C++增加了布尔型、引用类型、类类型三种数据类型,并在变量的定义上作了两种大的改变:

  对于第一个改变,似乎在C语言之后的版本标准中也改进了这一点,所以不要觉得和自己所学的C语言不同。
  对于第二个改变,似乎C语言目前还没有。看个例子。

6. 动态内存的分配与释放

  一般在程序中直接定义一个变量,如int a = 0;系统会自动在内存中给这个变量分配一块内存,但这种类型的变量不会在不使用之后就自动释放内存,只有在程序执行完毕后才会释放掉,不太经济。因此动态内存就显得很有必要了。
  在C语言中,有动态内存相关的关键词,即malloc(申请一块内存)和free(释放掉内存)。在C++中,也有与之对应的关键词。

#include 
using namespace std;
 
int example1()
{
  //可以在new后面直接赋值
  int *p = new int(3);
  //也可以单独赋值
  //*p = 3;
 
  //如果不想使用指针,可以定义一个变量,在new之前用“*”表示new出来的内容
  int q = *new int;
  q = 1;
  cout << q << endl;
 
  return *p;
}
 
int* example2()
{
  //当new一个数组时,同样用一个指针接住数组的首地址
  int *q = new int[3];  //但是需要注意,这种方式得到的数组没有初始化,值不确定。
  for(int i=0; i<3; i++)
    q[i] = i;
 
  return q;
}
 
struct student
{
  string name;
  int score;
};
 
 
student* example3()
{
  //这里是用一个结构体指针接住结构体数组的首地址
  //对于结构体指针,个人认为目前这种赋值方法比较方便
  student *stlist = new student[3]{{"abc", 90}, {"bac", 78}, {"ccd", 93}};
 
  return stlist;
}
 
 
 
int main()
{
  int e1 = example1();
  cout <<"e1: "<< e1 << endl;
 
  int *e2 = example2();
  for(int i=0; i<3; i++)
    cout << e2[i] << " ";
  cout << endl;
 
  student *st1 = example3();
 
  for(int i=0; i<3; i++)
    cout << st1[i].name << " " << st1[i].score << endl;
 
  return 0;
}

  注:代码来源

delete [] p; //p是用new分配的一个数组首地址指针
7. 引用

  引用是C++语言的一个特殊的数据类型描述,用于在程序的不同部分使用两个以上的变量名指向同一地址,使得对其中任一个变量的 *** 作实际上都是对同一地址单元进行的。
  在这种两个以上变量名的关系上,被声明为引用类型的变量名则是实际变量名的别名。
  引用运算符为&,声明引用的一般形式为:数据类型 &引用变量名 = 变量名; 看个例子

#include    
using namespace std;
void main()
{
	int a=10;
   	int &b=a;
	a=a*a;
	cout<<a<<b<<endl;
	b=b/5;
	cout<<a<<b<<endl;
}

在这个代码中,不管是对a还是b的运算,都会改变其对应地址的值,因此两次输出得到的结果不同。
  在使用引用时,有一些注意事项:

int num=50;
int &ref1=num;
int &ref2=ref1;
ref2=100;			// num被修改为100

  对于引用,最为经典的程序就是交换两个数的值的函数。【附:常用的交换两个数的函数写法】

#include      
using namespace std;

void swap(int &a, int &b)  //传入的参数为两个数的引用,这样就能通过改变引用值来改变实参的值。
{
	int temp;
	temp=a;
	a=b;
    b=temp;
}

int main( )
{
	int i=3 , j=5;
    swap(i , j);
    cout << "i=" << i << "j=" << j << endl;
	return 0;
}

C++中的引用在函数也有应用,不仅仅是参数可以用引用,返回值也可以使用,具体可以参考一下这篇博客,讲得非常详细。

8. const关键字

  当我们需要定义一些不需要更改或者不能被更改的量时,就会用到const关键字。值得一提的是,在C和C++中,都有const这个关键字,都是表示一个变量为常量,但二者具有较大的差别。具体可以看一下这篇博客。
  总结来说,大致是 C语言中的const关键字修饰的变量不能直接赋值改变,但可以通过指针来改变;而C++中不能通过指针来改变变量的值。
  此外,const关键词还可以修饰函数,一般在定义函数放在函数后面,表示该函数为常成员函数,它一般在类中使用,表示不能更改类中的成员变量,具体可以参考这篇博客。

9. 字符串

  在C语言中,如果要使用字符串,一般都是用字符数组来表示。且其最后一个元素必须为'string'。在C++中,提供了一种既方便又好用的

  • string类型的字符串不同于C风格的字符串,它的末尾没有
  • string类型的字符串可以直接通过cin输入;
  • 字符;类型。

    附:string常用用法总结

    10. 函数新特性 10.1 声明与定义

      C++中的函数与C中相同,如果使用先于定义,那就要在使用前声明。 且函数声明时可以省略形参,只保留形参数据类型。

    10.2 内置函数【内联函数】

      一般来说,如果要调用一个函数,都要先中断主程序的运行,并记录现场(PC指针等),然后在调用完函数之后又要回到中断点,并恢复现场,这个过程中虽然不是很麻烦,但是如果调用太过频繁,那这个时间也是很可观的,为了避免这个问题,优化程序时会将短的且需要频繁调用的函数设置为内置函数,这样相当于调用这个函数时直接把程序接到主程序中,节约了执行时间。
      使用内置函数的方法很简单,即 在①声明函数 或 ②声明和定义函数时在函数前面加上关键词include。看个例子:

    usingnamespace 
    ; inline stdint
    max ( int,int,int);//声明的时候在前面加上inlineint  main
    
    ( )int=
    {
    	10 i , =20j , =30k , ;=mmax
    	m (,,i)j;k<<"max ="
    	cout<<<<;mgetcharendl(
    	);return0
    	; }inline
    int
    
    max ( int,int a,int b)//其实定义的时候可以不加inline cif (
    {
    	)=b>a; aifb(
    	)=c>a; areturnc;
    	} a附:代码来源
    补充:如果在定义类时,直接定义函数,则该函数默认会被设置成内置函数。
    

    //函数定义时

      float

    10.3 带缺省参数的函数(参数有默认值)

      C++中,在函数声明和定义【如果分开的话,都要加上默认值】的时候,可以为形参指定一个缺省值,即不传这个参数时它取一个默认值,举个例子:

    area
    ( float=6.5 r ) return;
    {
    	} r//函数被调用时
    float
    
    =
    area a ( );//得到的a为6.5float  =
    area b ( 5.6);//得到的b为5.6返回值可相同可不同  #
    

      需要注意的是,如果有多个缺省参数,那么参数应该从右往左定义,缺省参数的右边不能存在未指定默认值的参数。

    这个很容易理解,如果缺省参数右边还有未指定缺省值的参数,那么在传参的时候就不确定是哪个参数了。

    10.4 函数重载(overload)【重要概念】

      在C语言中,是不允许有同名的函数存在的,但在C++中,这一点是被允许的,即函数重载。
      所谓函数重载,是指两个函数同名,但是二者的参数个数或参数类型不同【include】,那么在调用时,编译器会自动根据实参和形参的个数和类型的最佳匹配,来确定调用哪个函数。举个例子:

    usingnamespace             
    ; int stdmax
    
    ( int,int a,int b)//max有三个参数 cif (
    {
    	)=b>a; aifb(
       	)=c>a; areturnc;
       	} aint 
    max
    
    ( int,int a)//max有两个参数 bif  (
    {
    	)returna>b;  else areturn 
        ;    } bvoid 
    main
    
    ( )int=
    {
    	10 a,=7b,=-c2;<< max
        cout( ,)b<<c; //调用第二个max函数endl<<  max
       	cout( ,,a)b<<c; //调用第一个max函数endl } //如果定义这样两个函数:
    int
    


      另外,结合带缺省值参数的函数的概念,自然可以想到,函数重载时,不能与缺省参数调用相冲突,看个例子:

    f
    ( int,float a) ; bvoidf
    ( int,float a, int b= 0 c);//那么在如下调用时:f
    
    (
    10,1.2) ;//就不知道调用的是哪个函数[+++]
    [+++]
    
    三、VS2005

      以上内容从C++相比于C的一些改变之处对C++有了一个整体的介绍,基本上能够让人有一个大致的认识,接下来就是介绍开发C++的最基础的工具——VS2005。为什么不用高版本的VS比如VS2019呢?因为对于初学者来说,VS2019增加了很多不必要的东西,它一个空项目就快100M,对于初学者来说没有必要。
      由于VS2005的版本太老,和当下一些流行的编译器如VSC没办法相比,因此为了优化自己的编程体验,这里总结了一些辅助措施,来提升编程效率和编程体验。

    前面提到,VS2005编译器对应的C++版本是C++98,根据自己的需要选择。

    1. 界面认识

      打开VS2005时看到的界面如下所示:

      这个界面主要是可以看到最近打开的项目,还是非常常用的。

    2. 基本使用

      从学C语言我们就知道,一个编译性的语言,一般要经历编辑==>编译==>运行三个过程。VS2005也是这样的流程。

    3. 字体、快捷键等设置

      一个编译器最基本的设置就是设置代码的显示字体和一些快捷键了,这对于老旧的VS2005来说还是很有必要的。
      打开“工具”==>“选项”

    设置上自己想要的字体即可。


      对于VS2005中快捷键的设置,我有点奇怪,为什么注释这样常用的 *** 作的快捷键要按两次——Ctrl + K,Ctrl + C,难以接受,因此想要自定义一个常用的快捷键,同样打开 “工具” ==>“选项”:

    但是遗憾的是,VS2005中不支持不同指令用一个快捷键,因此也就无法实现按Ctrl + /就注释代码,再按一下就取消注释,只能设置两个快捷键。

    4. 代码联想

      由于VS2005版本太老了,所以像代码联想这种相对高级的功能就不具备,这样编程体验也不好,也没有什么办法能够补救呢?还真有,那就是装插件。VS有一个非常有名的插件,那就是VAssist,能够实现多种语言的代码联想,但这是一个收费软件,如果只是学习使用可以去找一个破解版,其安装与使用可以参考这篇博客。

    )
    File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
    File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
    File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
    Error[8]: Undefined offset: 743, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
    File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

    本文目录

    前言

      最近要完成一个WinSock编程的大作业,由于要求太简单,因此想要做一个窗口界面出来,于是想到两年前小学期学得很烂的C++及.NET,便把之前的课件翻出来重新学了一遍,同时想着写一篇博客记录一下。

    参考链接

      以下参考链接来自使用过程中遇到的一些问题查询的结果,会按照序号来命名,文中有对应标注。

    一、概述

      把课件整体学了一遍之后,发现老师课件的思路非常清晰明确且非常具有逻辑性,因此本博客也打算按照当时老师的思路来行文。首先大致介绍C++的一些特性,然后再重点介绍面向对象编程中的一些重点概念,要求读者具有C语言基础。最后再简单介绍开发工具VS2005的一些使用技巧。

    二、C++初步

      众所周知,C++语言的诞生就是基于C语言的,或者说C++是一个更好的C,同时也兼容C,其中最大的区别可能就是C++引入了类的机制,最初的C++也被称为“带类的C”(C language with class),之后才正式改名为C++。

      这里需要注意的是,C++问世之后,并不是说C语言就停滞发展了,二者在之后的时间中都在不断发展,在不断更新标准,其发展历程可以参考这篇文章,讲得非常详细。因此个人建议不必纠结它们中的某个细节是怎么发展更新的,只需要知道目前最新的版本即可

      本博客中根据老师课件的表述,应该是以C++98标准来展开讲述,而且使用的工具——VS 2005也只支持这个标准,虽然版本有点老,但是个人认为对入门C++还是足够了的,因为基本的一些概念在之后的版本更新中也没有太多变化。

    附:VS,GCC个版本与C++标准的对应关系

    0. 从C到C++

      C++(C plus plus)是C语言的超集,完全兼容C语言,它保持了C的简洁、高效和接近汇编语言等特点,同时对C的类型系统进行了改革和扩充,当然最为重要的还是它支持面向对象的方法编程(C++不是一个纯正的面向对象的语言)。因此在概念上不同于C,应按C++的方式来理解使用它。下面将从以下十个方面来讲述C++与C语言中不同之处,方面读者快速建立印象。

    1. 文件扩展名

      为了使得编译器能够区分是C语言还是C++语言,C++语言体系规定用 “.cpp” (意即 C Plus Plus)作为C++语言源文件的扩展名以区别于C语言用的 “.c” 文件扩展名。
      但是C++中头文件的扩展名仍然为 “.h” 。因此Arduino中调用的库一般都是一个.h文件配一个.cpp文件。

    为什么还要强调文件扩展名呢?
    可能对于目前一些高版本的编译器来说其实没什么差别,但是对于嵌入式等硬件差别还是存在的,不能随便写扩展名。

    2. 名字空间

      名字空间的概念是C++独有的,它相当于一个更加灵活的文件域,一般也叫作用域。首先来看一个基础的C++程序:

    #include 
    using namespace std;
    
    int main()
    {
    	int i = 3;
    	cout << "i = " <<i<<endl;
    	return 0;
    }
    

    其中的namespace关键词就是用来说明名字空间,std相当于一个标准的命名空间,里面有cout等C++基本的函数,因此在程序的开头要以using namespace std;来声明使用这个命名空间,这样就能使用其内部的函数或变量了。

      注意:在使用using namespace std;时,#include 后面是没有.h的。

      那能不能自定义一个名字空间呢?
      答案是肯定的。如果想自定义一个名字空间,可以用关键词namespace来定义,和定义一个类差不多。

    namespace  ns1
    {
         float a,b,c;
         void fun1(){……}
    }
    

    这样相当于给一些变量和函数限定的范围,因此使用的时候,需要使用作用域符::来表示使用的变量所在的名字空间。举个例子:

    namespace  ns1
    {
    	int  i=10;
    }
    namespace  ns2
    {
    	int  i=20;
    }
    
    #include      
    using namespace  std;
    
    int main( )
    {
    	int  i=3;
    	cout<<"i="<<i<<endl;  //默认作用域中的i变量
    	cout <<"i="<< ns1::i<<endl;//ns1作用域中的i变量
    	cout <<"i="<< ns2::i<<endl;//ns2作用域中的i变量
    	return 0;
    }
    

      通过上面这个例子,我们还可以总结出名字空间的两种用法:①使用using;②使用作用域符::。显然,如果涉及的函数或变量较少,可以使用作用域符;如果需要频繁使用到某名字空间的变量或函数,则可以使用using一个程序里面可以使用多个using,但其作用域中不能有冲突的变量或函数

      对于有结构体和类的概念的同学可能会问:这个和类有什么区别呢?
      确实是一个好问题,经过查找资料找到一篇相对完整的教程【链接】,里面对名字空间有详细的讲述,这其中,我认为和类相比最为不一样的就是名字空间是开放的,可以在使用过程中增添内容。看个例子。

    #include 
    using namespace std;
    
    namespace A {
        int a = 100;
        int b = 200;
    }
    //将c添加到已有的命名空间A中
    namespace A {
        int c = 300;
    }
    void test04()
    {
        cout<<"A中a = "<<A::a<<endl;//100
        cout<<"A中c = "<<A::c<<endl;//200
    }
    
    3. 作用域与作用域符

      在上一节名字空间中,我们对作用域有了一定的概念,但其实这个概念还可以扩展到局部变量和全局变量的范围。
      通常情况下,如果全局变量与局部变量同名,那么局部变量在其作用域内拥有较高的优先级。
      在C++中,提供一个作用域运算符::,它能指定所需要的作用域。来看个例子。

    #include    
    using namespace std;
    float a=2.4;          // 全局变量
    void main()
    {
    	int a=8;          // 局部变量
      	cout<<a<<endl;
      	cout<<::a<<endl;  // ::a表示全局作用域中的变量a
    } 
    

      需要注意的是,作用域符不能访问函数中的局部变量!

    4. 输入输出


      其中,<<在C语言中是移位运算符,而这里用来表示输出流,这属于是运算符重载,具体看后面的教程。

      这里对于初学者来说可能会混记的是cin和cout运算符分不清,这里我给的建议是,把cin和cout想象成一个端口,然后在cin和cout左边是输入输出终端,右边是需要输入输出的内容,这样根据数据的流向就能判断符号的方向了。

    5. 变量类型与定义

      C++增加了布尔型、引用类型、类类型三种数据类型,并在变量的定义上作了两种大的改变:

      对于第一个改变,似乎在C语言之后的版本标准中也改进了这一点,所以不要觉得和自己所学的C语言不同。
      对于第二个改变,似乎C语言目前还没有。看个例子。

    6. 动态内存的分配与释放

      一般在程序中直接定义一个变量,如int a = 0;系统会自动在内存中给这个变量分配一块内存,但这种类型的变量不会在不使用之后就自动释放内存,只有在程序执行完毕后才会释放掉,不太经济。因此动态内存就显得很有必要了。
      在C语言中,有动态内存相关的关键词,即malloc(申请一块内存)和free(释放掉内存)。在C++中,也有与之对应的关键词。

    #include 
    using namespace std;
     
    int example1()
    {
      //可以在new后面直接赋值
      int *p = new int(3);
      //也可以单独赋值
      //*p = 3;
     
      //如果不想使用指针,可以定义一个变量,在new之前用“*”表示new出来的内容
      int q = *new int;
      q = 1;
      cout << q << endl;
     
      return *p;
    }
     
    int* example2()
    {
      //当new一个数组时,同样用一个指针接住数组的首地址
      int *q = new int[3];  //但是需要注意,这种方式得到的数组没有初始化,值不确定。
      for(int i=0; i<3; i++)
        q[i] = i;
     
      return q;
    }
     
    struct student
    {
      string name;
      int score;
    };
     
     
    student* example3()
    {
      //这里是用一个结构体指针接住结构体数组的首地址
      //对于结构体指针,个人认为目前这种赋值方法比较方便
      student *stlist = new student[3]{{"abc", 90}, {"bac", 78}, {"ccd", 93}};
     
      return stlist;
    }
     
     
     
    int main()
    {
      int e1 = example1();
      cout <<"e1: "<< e1 << endl;
     
      int *e2 = example2();
      for(int i=0; i<3; i++)
        cout << e2[i] << " ";
      cout << endl;
     
      student *st1 = example3();
     
      for(int i=0; i<3; i++)
        cout << st1[i].name << " " << st1[i].score << endl;
     
      return 0;
    }
    

      注:代码来源

    delete [] p; //p是用new分配的一个数组首地址指针
    
    7. 引用

      引用是C++语言的一个特殊的数据类型描述,用于在程序的不同部分使用两个以上的变量名指向同一地址,使得对其中任一个变量的 *** 作实际上都是对同一地址单元进行的。
      在这种两个以上变量名的关系上,被声明为引用类型的变量名则是实际变量名的别名。
      引用运算符为&,声明引用的一般形式为:数据类型 &引用变量名 = 变量名; 看个例子

    #include    
    using namespace std;
    void main()
    {
    	int a=10;
       	int &b=a;
    	a=a*a;
    	cout<<a<<b<<endl;
    	b=b/5;
    	cout<<a<<b<<endl;
    }
    

    在这个代码中,不管是对a还是b的运算,都会改变其对应地址的值,因此两次输出得到的结果不同。
      在使用引用时,有一些注意事项:

    int num=50;
    int &ref1=num;
    int &ref2=ref1;
    ref2=100;			// num被修改为100
    

      对于引用,最为经典的程序就是交换两个数的值的函数。【附:常用的交换两个数的函数写法】

    #include      
    using namespace std;
    
    void swap(int &a, int &b)  //传入的参数为两个数的引用,这样就能通过改变引用值来改变实参的值。
    {
    	int temp;
    	temp=a;
    	a=b;
        b=temp;
    }
    
    int main( )
    {
    	int i=3 , j=5;
        swap(i , j);
        cout << "i=" << i << "j=" << j << endl;
    	return 0;
    }
    

    C++中的引用在函数也有应用,不仅仅是参数可以用引用,返回值也可以使用,具体可以参考一下这篇博客,讲得非常详细。

    8. const关键字

      当我们需要定义一些不需要更改或者不能被更改的量时,就会用到const关键字。值得一提的是,在C和C++中,都有const这个关键字,都是表示一个变量为常量,但二者具有较大的差别。具体可以看一下这篇博客。
      总结来说,大致是 C语言中的const关键字修饰的变量不能直接赋值改变,但可以通过指针来改变;而C++中不能通过指针来改变变量的值。
      此外,const关键词还可以修饰函数,一般在定义函数放在函数后面,表示该函数为常成员函数,它一般在类中使用,表示不能更改类中的成员变量,具体可以参考这篇博客。

    9. 字符串

      在C语言中,如果要使用字符串,一般都是用字符数组来表示。且其最后一个元素必须为'string'。在C++中,提供了一种既方便又好用的

  • string类型的字符串不同于C风格的字符串,它的末尾没有
  • string类型的字符串可以直接通过cin输入;
  • 字符;类型。

    附:string常用用法总结

    10. 函数新特性 10.1 声明与定义

      C++中的函数与C中相同,如果使用先于定义,那就要在使用前声明。 且函数声明时可以省略形参,只保留形参数据类型。

    10.2 内置函数【内联函数】

      一般来说,如果要调用一个函数,都要先中断主程序的运行,并记录现场(PC指针等),然后在调用完函数之后又要回到中断点,并恢复现场,这个过程中虽然不是很麻烦,但是如果调用太过频繁,那这个时间也是很可观的,为了避免这个问题,优化程序时会将短的且需要频繁调用的函数设置为内置函数,这样相当于调用这个函数时直接把程序接到主程序中,节约了执行时间。
      使用内置函数的方法很简单,即 在①声明函数 或 ②声明和定义函数时在函数前面加上关键词include。看个例子:

    usingnamespace 
    ; inline stdint
    max ( int,int,int);//声明的时候在前面加上inlineint  main
    
    ( )int=
    {
    	10 i , =20j , =30k , ;=mmax
    	m (,,i)j;k<<"max ="
    	cout<<<<;mgetcharendl(
    	);return0
    	; }inline
    int
    
    max ( int,int a,int b)//其实定义的时候可以不加inline cif (
    {
    	)=b>a; aifb(
    	)=c>a; areturnc;
    	} a附:代码来源
    补充:如果在定义类时,直接定义函数,则该函数默认会被设置成内置函数。
    

    //函数定义时

      float

    10.3 带缺省参数的函数(参数有默认值)

      C++中,在函数声明和定义【如果分开的话,都要加上默认值】的时候,可以为形参指定一个缺省值,即不传这个参数时它取一个默认值,举个例子:

    area
    ( float=6.5 r ) return;
    {
    	} r//函数被调用时
    float
    
    =
    area a ( );//得到的a为6.5float  =
    area b ( 5.6);//得到的b为5.6返回值可相同可不同  #
    

      需要注意的是,如果有多个缺省参数,那么参数应该从右往左定义,缺省参数的右边不能存在未指定默认值的参数。

    这个很容易理解,如果缺省参数右边还有未指定缺省值的参数,那么在传参的时候就不确定是哪个参数了。

    10.4 函数重载(overload)【重要概念】

      在C语言中,是不允许有同名的函数存在的,但在C++中,这一点是被允许的,即函数重载。
      所谓函数重载,是指两个函数同名,但是二者的参数个数或参数类型不同【include】,那么在调用时,编译器会自动根据实参和形参的个数和类型的最佳匹配,来确定调用哪个函数。举个例子:

    usingnamespace             
    ; int stdmax
    
    ( int,int a,int b)//max有三个参数 cif (
    {
    	)=b>a; aifb(
       	)=c>a; areturnc;
       	} aint 
    max
    
    ( int,int a)//max有两个参数 bif  (
    {
    	)returna>b;  else areturn 
        ;    } bvoid 
    main
    
    ( )int=
    {
    	10 a,=7b,=-c2;<< max
        cout( ,)b<<c; //调用第二个max函数endl<<  max
       	cout( ,,a)b<<c; //调用第一个max函数endl } //如果定义这样两个函数:
    int
    


      另外,结合带缺省值参数的函数的概念,自然可以想到,函数重载时,不能与缺省参数调用相冲突,看个例子:

    f
    ( int,float a) ; bvoidf
    ( int,float a, int b= 0 c);//那么在如下调用时:f
    
    (
    10,1.2) ;//就不知道调用的是哪个函数
    [+++]
    
    三、VS2005

      以上内容从C++相比于C的一些改变之处对C++有了一个整体的介绍,基本上能够让人有一个大致的认识,接下来就是介绍开发C++的最基础的工具——VS2005。为什么不用高版本的VS比如VS2019呢?因为对于初学者来说,VS2019增加了很多不必要的东西,它一个空项目就快100M,对于初学者来说没有必要。
      由于VS2005的版本太老,和当下一些流行的编译器如VSC没办法相比,因此为了优化自己的编程体验,这里总结了一些辅助措施,来提升编程效率和编程体验。

    前面提到,VS2005编译器对应的C++版本是C++98,根据自己的需要选择。

    1. 界面认识

      打开VS2005时看到的界面如下所示:

      这个界面主要是可以看到最近打开的项目,还是非常常用的。

    2. 基本使用

      从学C语言我们就知道,一个编译性的语言,一般要经历编辑==>编译==>运行三个过程。VS2005也是这样的流程。

    3. 字体、快捷键等设置

      一个编译器最基本的设置就是设置代码的显示字体和一些快捷键了,这对于老旧的VS2005来说还是很有必要的。
      打开“工具”==>“选项”

    设置上自己想要的字体即可。


      对于VS2005中快捷键的设置,我有点奇怪,为什么注释这样常用的 *** 作的快捷键要按两次——Ctrl + K,Ctrl + C,难以接受,因此想要自定义一个常用的快捷键,同样打开 “工具” ==>“选项”:

    但是遗憾的是,VS2005中不支持不同指令用一个快捷键,因此也就无法实现按Ctrl + /就注释代码,再按一下就取消注释,只能设置两个快捷键。

    4. 代码联想

      由于VS2005版本太老了,所以像代码联想这种相对高级的功能就不具备,这样编程体验也不好,也没有什么办法能够补救呢?还真有,那就是装插件。VS有一个非常有名的插件,那就是VAssist,能够实现多种语言的代码联想,但这是一个收费软件,如果只是学习使用可以去找一个破解版,其安装与使用可以参考这篇博客。

    )
    File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
    File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
    File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
    【C++】(一) C++初步,从C到C++_C_内存溢出

    【C++】(一) C++初步,从C到C++

    【C++】(一) C++初步,从C到C++,第1张

    本文目录
    • 前言
    • 参考链接
    • 一、概述
    • 二、C++初步
      • 0. 从C到C++
      • 1. 文件扩展名
      • 2. 名字空间
      • 3. 作用域与作用域符
      • 4. 输入输出
      • 5. 变量类型与定义
      • 6. 动态内存的分配与释放
      • 7. 引用
      • 8. const关键字
      • 9. 字符串
      • 10. 函数新特性
        • 10.1 声明与定义
        • 10.2 内置函数【内联函数】
        • 10.3 带缺省参数的函数(参数有默认值)
        • 10.4 函数重载(overload)【重要概念】
    • 三、VS2005
      • 1. 界面认识
      • 2. 基本使用
      • 3. 字体、快捷键等设置
      • 4. 代码联想

    前言

      最近要完成一个WinSock编程的大作业,由于要求太简单,因此想要做一个窗口界面出来,于是想到两年前小学期学得很烂的C++及.NET,便把之前的课件翻出来重新学了一遍,同时想着写一篇博客记录一下。

    参考链接

      以下参考链接来自使用过程中遇到的一些问题查询的结果,会按照序号来命名,文中有对应标注。

    • xxx
    一、概述

      把课件整体学了一遍之后,发现老师课件的思路非常清晰明确且非常具有逻辑性,因此本博客也打算按照当时老师的思路来行文。首先大致介绍C++的一些特性,然后再重点介绍面向对象编程中的一些重点概念,要求读者具有C语言基础。最后再简单介绍开发工具VS2005的一些使用技巧。

    二、C++初步

      众所周知,C++语言的诞生就是基于C语言的,或者说C++是一个更好的C,同时也兼容C,其中最大的区别可能就是C++引入了类的机制,最初的C++也被称为“带类的C”(C language with class),之后才正式改名为C++。

      这里需要注意的是,C++问世之后,并不是说C语言就停滞发展了,二者在之后的时间中都在不断发展,在不断更新标准,其发展历程可以参考这篇文章,讲得非常详细。因此个人建议不必纠结它们中的某个细节是怎么发展更新的,只需要知道目前最新的版本即可

      本博客中根据老师课件的表述,应该是以C++98标准来展开讲述,而且使用的工具——VS 2005也只支持这个标准,虽然版本有点老,但是个人认为对入门C++还是足够了的,因为基本的一些概念在之后的版本更新中也没有太多变化。

    附:VS,GCC个版本与C++标准的对应关系

    0. 从C到C++

      C++(C plus plus)是C语言的超集,完全兼容C语言,它保持了C的简洁、高效和接近汇编语言等特点,同时对C的类型系统进行了改革和扩充,当然最为重要的还是它支持面向对象的方法编程(C++不是一个纯正的面向对象的语言)。因此在概念上不同于C,应按C++的方式来理解使用它。下面将从以下十个方面来讲述C++与C语言中不同之处,方面读者快速建立印象。

    1. 文件扩展名

      为了使得编译器能够区分是C语言还是C++语言,C++语言体系规定用 “.cpp” (意即 C Plus Plus)作为C++语言源文件的扩展名以区别于C语言用的 “.c” 文件扩展名。
      但是C++中头文件的扩展名仍然为 “.h” 。因此Arduino中调用的库一般都是一个.h文件配一个.cpp文件。

    为什么还要强调文件扩展名呢?
    可能对于目前一些高版本的编译器来说其实没什么差别,但是对于嵌入式等硬件差别还是存在的,不能随便写扩展名。

    2. 名字空间

      名字空间的概念是C++独有的,它相当于一个更加灵活的文件域,一般也叫作用域。首先来看一个基础的C++程序:

    #include 
    using namespace std;
    
    int main()
    {
    	int i = 3;
    	cout << "i = " <<i<<endl;
    	return 0;
    }
    

    其中的namespace关键词就是用来说明名字空间,std相当于一个标准的命名空间,里面有cout等C++基本的函数,因此在程序的开头要以using namespace std;来声明使用这个命名空间,这样就能使用其内部的函数或变量了。

      注意:在使用using namespace std;时,#include 后面是没有.h的。

      那能不能自定义一个名字空间呢?
      答案是肯定的。如果想自定义一个名字空间,可以用关键词namespace来定义,和定义一个类差不多。

    namespace  ns1
    {
         float a,b,c;
         void fun1(){……}
    }
    

    这样相当于给一些变量和函数限定的范围,因此使用的时候,需要使用作用域符::来表示使用的变量所在的名字空间。举个例子:

    namespace  ns1
    {
    	int  i=10;
    }
    namespace  ns2
    {
    	int  i=20;
    }
    
    #include      
    using namespace  std;
    
    int main( )
    {
    	int  i=3;
    	cout<<"i="<<i<<endl;  //默认作用域中的i变量
    	cout <<"i="<< ns1::i<<endl;//ns1作用域中的i变量
    	cout <<"i="<< ns2::i<<endl;//ns2作用域中的i变量
    	return 0;
    }
    

      通过上面这个例子,我们还可以总结出名字空间的两种用法:①使用using;②使用作用域符::。显然,如果涉及的函数或变量较少,可以使用作用域符;如果需要频繁使用到某名字空间的变量或函数,则可以使用using一个程序里面可以使用多个using,但其作用域中不能有冲突的变量或函数

      对于有结构体和类的概念的同学可能会问:这个和类有什么区别呢?
      确实是一个好问题,经过查找资料找到一篇相对完整的教程【链接】,里面对名字空间有详细的讲述,这其中,我认为和类相比最为不一样的就是名字空间是开放的,可以在使用过程中增添内容。看个例子。

    #include 
    using namespace std;
    
    namespace A {
        int a = 100;
        int b = 200;
    }
    //将c添加到已有的命名空间A中
    namespace A {
        int c = 300;
    }
    void test04()
    {
        cout<<"A中a = "<<A::a<<endl;//100
        cout<<"A中c = "<<A::c<<endl;//200
    }
    
    3. 作用域与作用域符

      在上一节名字空间中,我们对作用域有了一定的概念,但其实这个概念还可以扩展到局部变量和全局变量的范围。
      通常情况下,如果全局变量与局部变量同名,那么局部变量在其作用域内拥有较高的优先级。
      在C++中,提供一个作用域运算符::,它能指定所需要的作用域。来看个例子。

    #include    
    using namespace std;
    float a=2.4;          // 全局变量
    void main()
    {
    	int a=8;          // 局部变量
      	cout<<a<<endl;
      	cout<<::a<<endl;  // ::a表示全局作用域中的变量a
    } 
    

      需要注意的是,作用域符不能访问函数中的局部变量!

    4. 输入输出


      其中,<<在C语言中是移位运算符,而这里用来表示输出流,这属于是运算符重载,具体看后面的教程。

      这里对于初学者来说可能会混记的是cin和cout运算符分不清,这里我给的建议是,把cin和cout想象成一个端口,然后在cin和cout左边是输入输出终端,右边是需要输入输出的内容,这样根据数据的流向就能判断符号的方向了。

    5. 变量类型与定义

      C++增加了布尔型、引用类型、类类型三种数据类型,并在变量的定义上作了两种大的改变:

    • 允许在程序的任意位置定义变量(C98标准里面变量的位置只能在函数开头)
    • 允许直接使用结构体名定义变量。

      对于第一个改变,似乎在C语言之后的版本标准中也改进了这一点,所以不要觉得和自己所学的C语言不同。
      对于第二个改变,似乎C语言目前还没有。看个例子。

    6. 动态内存的分配与释放

      一般在程序中直接定义一个变量,如int a = 0;系统会自动在内存中给这个变量分配一块内存,但这种类型的变量不会在不使用之后就自动释放内存,只有在程序执行完毕后才会释放掉,不太经济。因此动态内存就显得很有必要了。
      在C语言中,有动态内存相关的关键词,即malloc(申请一块内存)和free(释放掉内存)。在C++中,也有与之对应的关键词。

    • new运算符
        new从内存中分配内存空间,并返回指向该内存的首地址,该地址存放于指针变量中。而且需要注意的是,new分配的空间是在堆上,而一般的变量定义是在栈上,(具体概念不用了解)因此在函数中用new声明的变量在函数外还能使用。
      使用格式:指针变量 = new 数据类型;如果不想用指针变量,也可以: 变量 = *new 数据类型
        eg:
    #include 
    using namespace std;
     
    int example1()
    {
      //可以在new后面直接赋值
      int *p = new int(3);
      //也可以单独赋值
      //*p = 3;
     
      //如果不想使用指针,可以定义一个变量,在new之前用“*”表示new出来的内容
      int q = *new int;
      q = 1;
      cout << q << endl;
     
      return *p;
    }
     
    int* example2()
    {
      //当new一个数组时,同样用一个指针接住数组的首地址
      int *q = new int[3];  //但是需要注意,这种方式得到的数组没有初始化,值不确定。
      for(int i=0; i<3; i++)
        q[i] = i;
     
      return q;
    }
     
    struct student
    {
      string name;
      int score;
    };
     
     
    student* example3()
    {
      //这里是用一个结构体指针接住结构体数组的首地址
      //对于结构体指针,个人认为目前这种赋值方法比较方便
      student *stlist = new student[3]{{"abc", 90}, {"bac", 78}, {"ccd", 93}};
     
      return stlist;
    }
     
     
     
    int main()
    {
      int e1 = example1();
      cout <<"e1: "<< e1 << endl;
     
      int *e2 = example2();
      for(int i=0; i<3; i++)
        cout << e2[i] << " ";
      cout << endl;
     
      student *st1 = example3();
     
      for(int i=0; i<3; i++)
        cout << st1[i].name << " " << st1[i].score << endl;
     
      return 0;
    }
    

      注:代码来源

    • delete运算符
        运算符delete用于释放new分配的内存空间,它的使用形式为:delete 指针变量;其中的指针变量保存着new动态分配的内存的首地址。
        如果该指针指向的是一个数组的首地址,那么在使用delete释放时就要加上一对中括号
    delete [] p; //p是用new分配的一个数组首地址指针
    
    • 使用注意事项
      • new获取的内存空间,必须用delete进行释放,且使用delete的指针必须是new分配的内存空间首地址;
      • 对一个指针,只能用一次delete
      • 使用new分配内存空间时,是可能会存在无法分配的情况(内存不足)此时其返回的指针为NULL,即为0,使用时,可以根据其返回值来判断内存是否分配成功;
      • 使用delete时,不用考虑数组的维数。
    7. 引用

      引用是C++语言的一个特殊的数据类型描述,用于在程序的不同部分使用两个以上的变量名指向同一地址,使得对其中任一个变量的 *** 作实际上都是对同一地址单元进行的。
      在这种两个以上变量名的关系上,被声明为引用类型的变量名则是实际变量名的别名。
      引用运算符为&,声明引用的一般形式为:数据类型 &引用变量名 = 变量名; 看个例子

    #include    
    using namespace std;
    void main()
    {
    	int a=10;
       	int &b=a;
    	a=a*a;
    	cout<<a<<b<<endl;
    	b=b/5;
    	cout<<a<<b<<endl;
    }
    

    在这个代码中,不管是对a还是b的运算,都会改变其对应地址的值,因此两次输出得到的结果不同。
      在使用引用时,有一些注意事项:

    • 在一行中声明多个引用变量时,要在每个变量前面都加上“&”;
    • 一个变量在声明为引用时必须进行初始化;
      比如int &a = b;是正确的代码;int &a;是错误的代码。
    • 引用变量与被引用变量数据类型应一致;像这样的代码float a; int &b = a;是错误的;
    • 注意将引用与指针区分开来,指针在定义时用的符号是*,一般和数据类型一起使用,&是取一个变量的地址,一般是定义完指针变量之后使用时才会用的,而引用则是在定义时就使用。
    • 可以对引用变量再次进行引用。如下代码:
    int num=50;
    int &ref1=num;
    int &ref2=ref1;
    ref2=100;			// num被修改为100
    

      对于引用,最为经典的程序就是交换两个数的值的函数。【附:常用的交换两个数的函数写法】

    #include      
    using namespace std;
    
    void swap(int &a, int &b)  //传入的参数为两个数的引用,这样就能通过改变引用值来改变实参的值。
    {
    	int temp;
    	temp=a;
    	a=b;
        b=temp;
    }
    
    int main( )
    {
    	int i=3 , j=5;
        swap(i , j);
        cout << "i=" << i << "j=" << j << endl;
    	return 0;
    }
    

    C++中的引用在函数也有应用,不仅仅是参数可以用引用,返回值也可以使用,具体可以参考一下这篇博客,讲得非常详细。

    8. const关键字

      当我们需要定义一些不需要更改或者不能被更改的量时,就会用到const关键字。值得一提的是,在C和C++中,都有const这个关键字,都是表示一个变量为常量,但二者具有较大的差别。具体可以看一下这篇博客。
      总结来说,大致是 C语言中的const关键字修饰的变量不能直接赋值改变,但可以通过指针来改变;而C++中不能通过指针来改变变量的值。
      此外,const关键词还可以修饰函数,一般在定义函数放在函数后面,表示该函数为常成员函数,它一般在类中使用,表示不能更改类中的成员变量,具体可以参考这篇博客。

    9. 字符串

      在C语言中,如果要使用字符串,一般都是用字符数组来表示。且其最后一个元素必须为'string'。在C++中,提供了一种既方便又好用的

  • string类型的字符串不同于C风格的字符串,它的末尾没有
  • string类型的字符串可以直接通过cin输入;
  • 字符;类型。

    • 使用string类型的字符要包含头文件#include
    • string str2 = str1;str1
    • string类型的字符可以直接像变量一样赋值.c_str())也是一个string字符串;
    • string字符串可以通过length()运算符来调用其内置的函数;
    • string类型的字符串转换为C风格的字符串可以使用+函数;
    • 如果要获取字符串长度可以调用+=函数;
    • string类型的字符串可以直接用[]
    • string类型的字符串还有很多函数可以使用,可以很方便地实现增删改查,具体可以参考下面的链接。
    • 来衔接多个字符串,且不用担心超出存储范围的问题;
    • string类型的字符串仍然可以通过inline加下标来访问其中的字符,和C一样,下标从0开始;
    • #

    附:string常用用法总结

    10. 函数新特性 10.1 声明与定义

      C++中的函数与C中相同,如果使用先于定义,那就要在使用前声明。 且函数声明时可以省略形参,只保留形参数据类型。

    10.2 内置函数【内联函数】

      一般来说,如果要调用一个函数,都要先中断主程序的运行,并记录现场(PC指针等),然后在调用完函数之后又要回到中断点,并恢复现场,这个过程中虽然不是很麻烦,但是如果调用太过频繁,那这个时间也是很可观的,为了避免这个问题,优化程序时会将短的且需要频繁调用的函数设置为内置函数,这样相当于调用这个函数时直接把程序接到主程序中,节约了执行时间。
      使用内置函数的方法很简单,即 在①声明函数 或 ②声明和定义函数时在函数前面加上关键词include。看个例子:

    usingnamespace 
    ; inline stdint
    max ( int,int,int);//声明的时候在前面加上inlineint  main
    
    ( )int=
    {
    	10 i , =20j , =30k , ;=mmax
    	m (,,i)j;k<<"max ="
    	cout<<<<;mgetcharendl(
    	);return0
    	; }inline
    int
    
    max ( int,int a,int b)//其实定义的时候可以不加inline cif (
    {
    	)=b>a; aifb(
    	)=c>a; areturnc;
    	} a附:代码来源
    补充:如果在定义类时,直接定义函数,则该函数默认会被设置成内置函数。
    

    //函数定义时

      float

    10.3 带缺省参数的函数(参数有默认值)

      C++中,在函数声明和定义【如果分开的话,都要加上默认值】的时候,可以为形参指定一个缺省值,即不传这个参数时它取一个默认值,举个例子:

    area
    ( float=6.5 r ) return;
    {
    	} r//函数被调用时
    float
    
    =
    area a ( );//得到的a为6.5float  =
    area b ( 5.6);//得到的b为5.6返回值可相同可不同  #
    

      需要注意的是,如果有多个缺省参数,那么参数应该从右往左定义,缺省参数的右边不能存在未指定默认值的参数。

    这个很容易理解,如果缺省参数右边还有未指定缺省值的参数,那么在传参的时候就不确定是哪个参数了。

    10.4 函数重载(overload)【重要概念】

      在C语言中,是不允许有同名的函数存在的,但在C++中,这一点是被允许的,即函数重载。
      所谓函数重载,是指两个函数同名,但是二者的参数个数或参数类型不同【include】,那么在调用时,编译器会自动根据实参和形参的个数和类型的最佳匹配,来确定调用哪个函数。举个例子:

    usingnamespace             
    ; int stdmax
    
    ( int,int a,int b)//max有三个参数 cif (
    {
    	)=b>a; aifb(
       	)=c>a; areturnc;
       	} aint 
    max
    
    ( int,int a)//max有两个参数 bif  (
    {
    	)returna>b;  else areturn 
        ;    } bvoid 
    main
    
    ( )int=
    {
    	10 a,=7b,=-c2;<< max
        cout( ,)b<<c; //调用第二个max函数endl<<  max
       	cout( ,,a)b<<c; //调用第一个max函数endl } //如果定义这样两个函数:
    int
    


      另外,结合带缺省值参数的函数的概念,自然可以想到,函数重载时,不能与缺省参数调用相冲突,看个例子:

    f
    ( int,float a) ; bvoidf
    ( int,float a, int b= 0 c);//那么在如下调用时:f
    
    (
    10,1.2) ;//就不知道调用的是哪个函数
    
    
    三、VS2005

      以上内容从C++相比于C的一些改变之处对C++有了一个整体的介绍,基本上能够让人有一个大致的认识,接下来就是介绍开发C++的最基础的工具——VS2005。为什么不用高版本的VS比如VS2019呢?因为对于初学者来说,VS2019增加了很多不必要的东西,它一个空项目就快100M,对于初学者来说没有必要。
      由于VS2005的版本太老,和当下一些流行的编译器如VSC没办法相比,因此为了优化自己的编程体验,这里总结了一些辅助措施,来提升编程效率和编程体验。

    前面提到,VS2005编译器对应的C++版本是C++98,根据自己的需要选择。

    1. 界面认识

      打开VS2005时看到的界面如下所示:

      这个界面主要是可以看到最近打开的项目,还是非常常用的。

    2. 基本使用

      从学C语言我们就知道,一个编译性的语言,一般要经历编辑==>编译==>运行三个过程。VS2005也是这样的流程。

    • 首先新建项目


      在这里其实也可以选择Win32,然后再选择空项目:



        到此,一个项目工程就创建好了,可以看一下项目文件夹,发现其实只有10M左右,还是非常小的。
    • 工程文件结构
      在创建完项目之后,我们可以在解决方案资源管理器窗口中看到三个文件夹

      一般来说,头文件主要是放.h文件,而源文件主要是放.cpp文件,资源文件主要是放一些编译好的.obj文件(如果有的话)
    • 添加、编辑文件
      确定文件结构之后,接下来就是添加文件并编辑了。
      直接在文件夹上右键,选择添加,新建项。

    • 编译运行
      添加文件之后,就是正常的编程过程了,编辑完成之后,需要编译和运行,这个建议使用工具栏的图标。

      如果在工具栏没找到,可以右键工具栏空白位置,然后勾选生成和调试选项,即可看到工具栏。或者在菜单栏中点击“生成”==>“生成解决方案”。在底下的输出栏中即可看到编译信息。

      此外,值得一提的是,在VS中,调试和运行是一个按钮,如果有断点就是调试,如果没有断点,就全部执行,相当于运行了,这个设计挺棒。同样,调试的一些 *** 作(单步运行等)也可以在工具栏中找到,如果没有,右键选择。
    • 调试技巧
      在VS2005中,可以在调试时查看局部变量的值,方法就是调出监视窗口。按下调试之后,程序停在某个断点时,点击菜单栏调试,可以看到可以调出很多窗口来辅助调试过程。

      此外,在设置断点,还可以设置为条件断点,将光标停留在断点附近,当光标变成尖头朝右时,如下图所示。

      然后再右键,可以选择条件断点。


      比如在一些循环中就可以设置在哪次循环中停在断点,其他次循环不停顿。
    3. 字体、快捷键等设置

      一个编译器最基本的设置就是设置代码的显示字体和一些快捷键了,这对于老旧的VS2005来说还是很有必要的。
      打开“工具”==>“选项”

    设置上自己想要的字体即可。


      对于VS2005中快捷键的设置,我有点奇怪,为什么注释这样常用的 *** 作的快捷键要按两次——Ctrl + K,Ctrl + C,难以接受,因此想要自定义一个常用的快捷键,同样打开 “工具” ==>“选项”:

    但是遗憾的是,VS2005中不支持不同指令用一个快捷键,因此也就无法实现按Ctrl + /就注释代码,再按一下就取消注释,只能设置两个快捷键。

    4. 代码联想

      由于VS2005版本太老了,所以像代码联想这种相对高级的功能就不具备,这样编程体验也不好,也没有什么办法能够补救呢?还真有,那就是装插件。VS有一个非常有名的插件,那就是VAssist,能够实现多种语言的代码联想,但这是一个收费软件,如果只是学习使用可以去找一个破解版,其安装与使用可以参考这篇博客。

    欢迎分享,转载请注明来源:内存溢出

    原文地址: http://outofmemory.cn/langs/1353437.html

    (0)
    打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
    上一篇 2022-06-14
    下一篇 2022-06-14

    发表评论

    登录后才能评论

    评论列表(0条)

    保存