第1章 C++的初步知识.docx

上传人:b****2 文档编号:23192356 上传时间:2023-05-15 格式:DOCX 页数:34 大小:28.60KB
下载 相关 举报
第1章 C++的初步知识.docx_第1页
第1页 / 共34页
第1章 C++的初步知识.docx_第2页
第2页 / 共34页
第1章 C++的初步知识.docx_第3页
第3页 / 共34页
第1章 C++的初步知识.docx_第4页
第4页 / 共34页
第1章 C++的初步知识.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

第1章 C++的初步知识.docx

《第1章 C++的初步知识.docx》由会员分享,可在线阅读,更多相关《第1章 C++的初步知识.docx(34页珍藏版)》请在冰豆网上搜索。

第1章 C++的初步知识.docx

第1章C++的初步知识

第1章C++的初步知识

上学期我们讲的是面向过程的C语言部分,这学期我们要讲解面向对象的C++部分。

C++保留了C语言原有的优点,增加了面向对象机制。

1.1从C到C++

C语言是结构化和模块化的语言,它是面向过程的。

能处理小规模的程序。

但当规模较大时会显示出它的不足。

为了解决这个软件危机,提出了面向对象的程序设计(objectorientedprogramming,OOP)思想。

C++保留了C语言原有的所有优点,增加了面向对象机制。

所以C++也称为“带类的C”。

C++对C的“增强”,表现在以下两个方面:

1、在原来面向过程的机制基础上,对C语言的功能作了扩充。

(本章将介绍补充部分)

2、增加了面向对象的机制。

在面向对象的程序设计中仍然要用到结构化程序设计的知识。

下面介绍C++对C的扩充,及与C的差别所在。

1.2最简单的C++程序

C++程序在结构上与C的差别如下:

1、标准C++规定main函数声明为int型,即此主函数带回一个整型的函数值。

程序如果正常执行,则操作系统返回数值0,否则返回数值-1。

2、系统头文件不带后缀.h,如:

#include

3、使用系统库时要使用命名空间std。

即使用usingnamespacestd;,这句话的意思是使用命名空间std。

C++标准库中的类和函数是在命名空间std中声明的,因此程序中如果需要用到C++标准库,就需要用usingnamespacestd;来声明,表示要用命名空间std中的内容。

例1.1最简单的只有输出的程序

#include

usingnamespacestd;

intmain()

{cout<<"ThisisaC++programm.\n";

//cout是对象名,称为输出流对象。

“<<”是插入运算符

return0;//没有此句会有警告。

最好加上此句

}

例1.2最简单的有输入的程序

#include

usingnamespacestd;

intmain()

{inta,b,sum;

cin>>a>>b;//cin是输入流对象。

“>>”是提取运算符

sum=a+b;

cout<<"a+b="<

return0;//没有此句会有警告。

最好加上此句

}

例1.3输入二个数x和y,求两个数中的大者。

(要求用函数实现,学生练习)

例1.4对学生信息进行输入与输出。

1)用结构体实现

#include

usingnamespacestd;

structStudent

{

intnum;

intscore;

};

voidinput(structStudent*ps)

{

cin>>ps->num;

cin>>ps->score;

}

voidoutput(structStudents)

{

cout<

cout<

}

intmain()

{

structStudents;

input(&s);

output(s);

}

以上数据与对数据的操作(函数)是分开的

2)用类来实现

classStudent

{

private:

intnum;

intscore;

public:

voidinput()

{

cin>>num;

cin>>score;

}

voidoutput()

{

cout<

cout<

}

};

intmain()

{

structStudents;

s.input();

s.output();

}

数据与对数据的操作(函数)是一个整体。

类中的函数也是一个成员,叫着成员函数。

数据成员被说明为私有的,在类外是不能使用的。

1.3C++对C的扩充

1.3.1C++的输入输出

在C++中是通过调用输入输出流库中的流对象cin和cout实现的。

流指的是来自设备或传给设备的一个数据流。

cout是输出流对象的名字,cin是输入流对象的名字。

一、输入流与输出流的基本操作

cout语句的一般格式为:

cout<<表达式1<<表达式2<<……<<表达式n;

cin语句的一般格式为:

cin>>变量1>>变量2>>……>>变量n;

当程序需要在屏幕上显示输出时,可以使用插入操作符"<<",向cout输出流中插入字符。

例如:

cout<<"Thisisaprogram.\n";

当程序需要执行键盘输入时,可以使用抽取操作符">>",从cin输人流中抽取字符。

例如:

inta;cin>>a;。

不管把什么基本数据类型的名字或值传给流,它都能懂。

例如,下面的程序是输出字符串和整数:

#include

usingnamespacestd;

intmain()

{cout<<"ThisisaC++program."<

cout<<"Thisis"

<<"aC++program."

<

cout<<"Thisis";

cout<<"aC++program.";

cout<

cout<<2;

cout<

return0;

}

从上面的程序可以看出,输出的写法可以在同一行串连也可以分在几行。

cin可以和cout一样的方式调整行,它自动识别变量位置和类型。

例如:

inta;floatb;charc;,则cin>>a>>b>>c;,也可以写成:

cin>>a;

cin>>b;

cin>>c

cin能够知道抽取的变量的类型,它将对a,b,c分别给出一个整型、浮点型和字符型数。

二、输入流与输出流中使用控制符(将在第七章中详细介绍)

1.3.2用const定义常变量

在C语言中常用#define命令来定义符号常量,实际上,只是进行字符置换,容易误解。

#include

usingnamespacestd;

#defineR2+3

intmain()

{cout<

return0;//没有此句会有警告。

最好加上此句

}

下面看C++提供的const定义常变量的方法就避免这个问题。

#include

usingnamespacestd;

constintR=2+3;

intmain()

{cout<

return0;//没有此句会有警告。

最好加上此句

}

1.3.3函数原型声明

在C++中,如果函数调用的位置在函数定义之前,则要求在函数调用之前必须对所调用的函数作函数原型声明,这是强制性的。

如有定义:

intmax(inta,intb)

{returna+b;

}

声明时必须写成:

intmax(inta,intb);或

intmax(intx,inty);或

intmax(int,int);

1.3.4函数的重载

1、为什么要用重载函数

在C中,在同一作用域中不能有同名的函数,每个函数必须有其唯一的名字,这样有时会令人生厌。

例如,求一个数的绝对值,由于要求命名唯一,所以对于不同的类型需要不同名字的函数:

intabs(int);返回整型参数的绝对值

longlabs(long)返回长整型参数的绝对值

doublefabs(double)返回双精度参数的绝对值

极其相似操作函数我们却起三个不同的名字,这样子不是很好管理,所以C++为了方便程序员编写程序特别引入了函数重载的概念来解决此问题。

C++允许在同一作用域用同一函数名定义多个函数,这些函数的参数个数和参数类型不相同,这些同名的函数用来实现不同的功能。

这就是函数的重载。

重载是用来描述同名函数具有相同或者相似功能,但数据类型或者是参数不同的函数管理操作的称呼。

同一个函数名可以用来代表不同功能的函数,也就是一名多用。

这几个函数所做的事情是一样的都是求绝对值。

因此,使用三个不同的函数名,看上去很笨拙,若给以同样的名字就会方便得多。

这就是重载技术。

这种技术在C++中早已用于基本数据类型运算,如加法只有一个名字+,但它可以用来加整数值、浮点值和指针值。

插入运算符“<<”和提取运算符“>>”既可以左移和右移也可以是输入输出运算符。

例如,上述3个函数的声明可以改为:

  intabs(int);

longabs(long);

 doubleabs(double);

C++用一种函数命名技术可以准确判断出应该使用哪个abs()函数。

例如:

  abs(-10);//调用intabs(int);

  abs(-1000000);//调用longabs(1ong);

  abs(-12.23);//调用doubleabs(double);

2、匹配重载函数的顺序

在调用一个重载函数f()时,编译器必须搞清函数名f究竟是指哪个函数。

这是靠将实参类型和所有被调用的f()函数的形参类型一一比较来判定的。

按下述3个步骤的先后顺序找到并调用那个函数:

(1)寻找一个严格的匹配,如果找到了,就用那个函数。

(2)通过内部转换寻求一个匹配,只要找到了,就用那个函数。

(3)通过用户定义的转换寻求一个匹配,若能查出有唯一的一组转换,就用那个函数  例如,重载函数print()的匹配:

    voidprint(double);

    voidprint(int);

    voidfunc()

    {

     print

(1);//匹配voidprint(int);

     print(1.0);//匹配voidprint(double);

     print('a');//匹配voidprint(int);

     print(3.1415f);//匹配voidprint(double);

    }

  例如,对于重载函数print()声明,其下面的函数调用将引起错误:

    voidprint(1ong);

    voidprint(double);

    voidfunc(inta)

    {  print(a);//error:

因为有二义性

    }

3、使用说明

(1)C++的函数如果在返回类型、参数类型、参数个数、参数顺序上有所不同,则认为是不同的。

但重载函数如果仅仅是返回类型不同,则是不够的。

例如,下面的声明是错误的:

    voidfunc(int);

    intfunc(int);

编译器无法区分函数调用"func(3)”是指上述哪一个重载函数。

因此重载函数至少在参数个数、参数类型或参数顺序上有所不同。

(2)typedef定义的类型只能使之相同于一个已存在的类型,而不是建立新的类型,所以不能用typedef定义的类型名来区分重载函数声明中的参数。

例如,下面的代码实际上是同一个函数:

    typedefINTint;

    voidfunc(intx){//...}

    voidfunc(INTx){//...)//error:

函数重复定义

编译器不能区分这两个函数的差别,INT只不过是int的另一种称呼而已;

(3)让重载执行不同的功能,是不好的编程风格。

同名函数应该具有相同的功能。

如果定义一个abs()函数而返回的却是一个数的平方根,该程序的可读性受到破坏。

下面我们用重载的概念来编写一个求3个数(分别是整数、实数、长整数的情况中最大数的程序。

P12例1.6

#include

usingnamespacestd;

intmax(inta,intb,intc)

{

if(b>a)

a=b;

if(c>a)

a=c;

returna;

}

floatmax(floata,floatb,floatc)

{

return(a>b?

a:

b)>c?

(a>b?

a:

b):

c;

}

longmax(longa,longb,longc)

{

intt;

if(a

t=a,a=b,b=t;

if(a

t=a,a=c,c=t;

returna;

}

intmain()

{

inta,b,c;

floatd,e,f;

longg,h,i;

cin>>a>>b>>c;

cin>>d>>e>>f;

cin>>g>>h>>i;

cout<

cout<

cout<

}

上例是函数的参数个数相同,但类型不同。

系统会根据实参的类型来匹配。

还可以参数个数不同,请看下例。

P13例1.7用一个函数求2个正整数或3个正整数的最大者。

#include

usingnamespacestd;

intmax(inta,intb)

{

returna>b?

a:

b;

}

intmax(inta,intb,intc)

{

return(a>b?

a:

b)>c?

(a>b?

a:

b):

c;

}

intmain()

{

inta,b,c;

cin>>a>>b>>c;

cout<

}

1.3.5函数模板

函数的重载可以实现一个函数名多用,将功能相同或类似的函数用同一个函数名来定义。

这样使编程者在调用同类函数时感到含义清楚,方法简单。

但是在程序中仍然要分别定义每一个函数。

例如:

求3个数中最大的数(分别考虑整数、双精度数、浮点数的情况)

#include

usingnamespacestd;

intmain()

{

intmax(inta,intb,intc);

doublemax(doublea,doubleb,doublec);

floatmax(floata,floatb,floatc);

inti1,i2,i3,i;

i1=10;i2=23;i3=13;

i=max(i1,i2,i3);

cout<<"i_max"<

doubled1,d2,d3,d;

d1=23,5;d2=45;d3=56.4;

d=max(d1,d2,d3);

cout<<"d_max"<

floatf1,f2,f3,f;

f1=34.3;f2=65.4;f3=56.4;

f=max(f1,f2,f3);

cout<<"f_max"<

}

intmax(inta,intb,intc)

{if(a

a=b;

if(a

a=c;

returna;

}

doublemax(doublea,doubleb,doublec)

{if(a

a=b;

if(a

a=c;

returna;

}

floatmax(floata,floatb,floatc)

{if(a

a=b;

if(a

a=c;

returna;

}

从上面的程序中可以看出,有3个max函数的函数体是完全相同的,只是形参的类型不同,也要分别定义,能否对此进行简化呢?

为了解决这个问题,C++提供了函数模板。

所谓函数模板就是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。

这个通用函数就称为函数模板。

凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。

在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。

我们将上面的例子用函数模板来实现

#include

usingnamespacestd;

template//模板声明,其中T为类型参数,会有不同数据类型的地方,

//以设定类型的变量替代。

Tmax(Ta,Tb,Tc)//定义一个通用函数,用T作虚拟的类型名

{

if(a

a=b;

if(a

a=c;

returna;

}

intmain()

{inti1,i2,i3,i;

i1=10;i2=23;i3=13;

i=max(i1,i2,i3);

cout<<"i_max"<

doubled1,d2,d3,d;

d1=23,5;d2=45;d3=56.4;

d=max(d1,d2,d3);

cout<<"d_max"<

floatf1,f2,f3,f;

f1=34.3;f2=65.4;f3=56.4;

f=max(f1,f2,f3);

cout<<"f_max"<

}

从上例可以看出,用函数模板比函数重载更为方便,程序简洁多了。

但应注意它只适用于函数体相同、函数的参数个数相同而类型不同的情况,如果参数的个数不同,则不能用函数模板。

例:

定义一个交换两变量值的模板函数,利用它来实现整数、浮点数、双精度数、字符串的交换。

(学生练习)

#include

#include

usingnamespacestd;

template//模板声明,其中T为类型参数

voidswap(T*a,T*b)//定义一个通用函数,用T作虚拟的类型名

{

T*temp;

*temp=*a;*a=*b;*b=*temp;

}

intmain()

{

inti1,i2;

i1=10;i2=23;

swap(i1,i2);

cout<<"i1="<

doubled1,d2;

d1=23,5;d2=45;

swap(d1,d2);

cout<<"d1="<

floatf1,f2;

f1=34.3;f2=65.4;

swap(f1,f2);

cout<<"f1="<

strings1,s2;

s1="good";s2="better";

swap(s1,s2);

cout<<"s1="<

}

模板函数调用时,类型实参与类型形参的匹配要求很苛刻。

下面来看一个实例。

#include

#include

usingnamespacestd;

template//模板声明,其中T为类型参数

voidswap(T*a,T*b)//定义一个通用函数,用T作虚拟的类型名

{

T*temp;

*temp=*a;*a=*b;*b=*temp;

}

voidf(doublea,doubleb)

{

return;

}

intmain()

{

intia=3;

doubledb=5.0;

f(ia,db);//okia的类型与double不同,但可以隐式转换为double,实现合法调用

swap(ia,db);//erroria与db的类型不同,不能统一到同一个类型上。

//模板类型参数没有隐式转换的说法,必须精确匹配,所以编译错误

}

1.3.6有默认参数的函数

1、默认参数的目的

C++可以给函数定义默认参数值。

通常,调用函数时,要为函数的每个参数给定对应的实参。

例如:

    voiddelay(intloops);//函数声明

   voiddelay(intloops)//函数定义

    {if(1oops==0)

      return;

     for(inti=0;i

    }

无论何时调用delay()函数,都必须给loops传一个值以确定时间。

但有时需要用相同的实参反复调用delay()函数。

C++可以给参数定义默认值。

如果将delay()函数中的loops定义成默认值1000,只需简单地把函数声明改为:

   voiddelay(intloops=1000);

这样,无论何时调用delay()函数,都不用给loops赋值,程序会自动将它当作值1000进行处理。

例如,调用:

    delay(2500);//loops设置为2500

    delay();//ok:

loops采用默认值1000

调用中,若不给出参数,则按指定的默认值进行工作。

允许函数默认参数值,是为了让编程简单,让编译器做更多的检查错误工作。

2、默认参数的声明

默认参数在函数声明中提供,当又有声明又有定义时,定义中不允许默认参数。

如果函数只有定义,则默认参数才可出现在函数定义中。

例如:

    voidpoint(int=3,int=4);//声明中给出默认值

    voidpoint(intx,inty)//定义中不允许再给出默认值

    {cout<

     cout<

    }

3、默认参数的顺序规定

如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左逐渐定义。

当调用函数时,只能向左匹配参数。

例如:

    voidfunc(inta=1,intb,intc=3,intd=4);//error

    voidfunc(inta,intb=2,intc=3,intd=4);//ok

voidfunc(inta,intb,intc=3,intd=4);//ok

voidfunc(inta,intb,intc,intd=4);//ok

请看下例:

#include

usingnamespacestd;

voidf1(inta,intb=2,intc=3,intd=4);

voidf2(inta,intb,intc=3,intd=4);

intmain()

{

f1(30);

f1(30,40);

f1(30,40,50);

f1(30,40,50,60);

f2(300,400);

f2(300,400,500);

f2(300,400,500,600);

return0;

}

vo

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1