Upload
maxima
View
108
Download
0
Embed Size (px)
DESCRIPTION
第 1 章 C++ 基础. 1.1 简单 C++ 程序. [ 例 Ex_Simple] 一个简单的 C++ 程序 #include void main() { double r, area; // 声明变量 coutr; // 从键盘上输入 r 的值 area = 3.14159 * r * r; // 计算面积 cout
Citation preview
第 1 章 C++ 基础
1.1 简单 C++ 程序[ 例 Ex_Simple] 一个简单的 C++ 程序 #include <iostream.h> void main() { double r, area; // 声明变量 cout<<" 输入圆的半径: "; // 显示提示信息 cin>>r; // 从键盘上输入 r 的值 area = 3.14159 * r * r; // 计算面积 cout<<“ 圆的面积为:” <<area<<“\n” ; // 输出面积 } 该程序经编译、连接、运行后,屏幕上显示:输入圆的半径:此时等待用户输入,当输入 10 并按 Enter 键后,屏幕显示:圆的面积为: 314.159Press any key to continue这就是程序运行的结果。
1.1 简单 C++ 程序[ 例 Ex_Root] 一个求解一元二次方程的 C++ 程序#include <iostream.h>#include <math.h>int GetRoot(float a, float b, float c, double *root);/* 声明一个全局函
数 */void main(){ float a = 2.0, b = 6.0, c = 3.0; // 定义并初始化变量 double root[2]; int n = GetRoot(a, b, c, roo // 调用函数 if (n<1)
cout<<" 方程无根! ";else { cout<<" 方程有 "<<n<<" 根 :\n"; for (int i=0; i<n; i++) // 循环输出所有的根 cout<<" 根 "<<i+1<<": "<<root[i]<<"\t"; } cout<<endl;}
1.1 简单 C++ 程序// 求一元二次方程的根,函数返回根的个数int GetRoot(float a, float b, float c, double *root){ double delta, deltasqrt;
delta = b*b - 4.0 * a * c;if (delta<0.0) return 0; // 无根deltasqrt = sqrt(delta);if (a!=0.0) {
root[0] = (-b + deltasqrt)/(2.0 * a);root[1] = (-b - deltasqrt)/(2.0 * a);
} elseif (b!=0.0) root[0] = root[1] = -c/b;else return 0;
}if (root[0] == root[1]) return 1;else return 2
方程有 2 根 :根 1: -0.633975 根 2: -2.36603
1.2.1 从结构到类 [ 例 Ex_StructToClass] 从结构到类的示例#include <iostream.h>struct STUSCORE {
char strName[12]; // 姓名char strStuNO[9]; // 学号float fScore[3]; // 三门课程成绩
};float GetAverage(STUSCORE one) // 计算平均成绩{
return (float)((one.fScore[0] + one.fScore[1] + one.fScore[2])/3.0);}void main(){
STUSCORE one={"LiMing", "21020501", {80,90,65}};cout<<one.strName<<" 的平均成绩为: "<<GetAverage(one)<<"\
n";}运行结果如下:LiMing 的平均成绩为: 78.3333
1.2.2 类的定义 类一般分为声明部分和实现部分。
类体
C++中定义类的一般格式如下: class <类名 >
{
private:[< 私有数据和函数
>] public:
[<公有数据和函数>]
}; <各个成员函数的实现 >
class 是定义类的关键字, class 的后面是用户定义的类名,用 大写的 C 字母开始的标识符作为类名, C 用来表示类 (Class) ,以与对象、函数及其他数据类型相区别。类中的数据和函数是类的成员,称为数据成员和成员函数。
1.2.2 类的定义 CStuScore 类包含了 SetScore 和 GetAverage 成员函数,分别用来输入成绩和返回计算后的平均成绩:class CStuScore {public: // 公有类型声明 char strName[12]; // 姓名 char strStuNO[9]; // 学号 void SetScore(float s0, // 成员函数:设置三门课成绩 { fScore[0] = s0; fScore[1] = s1; fScore[2] = s2; } float GetAverage(); private: // 私有类型声明 float fScore[3]; // 三门课程成绩 }; // 注意分号不能省略 float CStuScore::GetAverage() { return (float)((fScore[0] + fScore[1] + fScore[2])/3.0); } 类 CStuScore 中,成员函数 SetScore 是在类体中定义, GetAverage 是类
的外部定义,注意两者的区别。
1.2.2 类的定义定义类时还应注意:
( 1 ) 在“ public:” 或“ private:” 后面成员都是公有或私有的,直到下一个“ public:” 或“ private:” 出现为止。
( 2 )关键字 public 和 private 在类中出现多次,前后的顺序没有关系。
( 3 )除了 public 和 private 外,关键字 protected 也可修饰成员的类型。
( 4 )数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针等。
( 5 )将类单独存放在一个文件中或将类的声明放在 .h文件中而将成员函数的实现放在与 .h 文件同名的 .cpp 文件中。
Visual C++ 6.0 为用户创建的应用程序框架中都是将各个类以 .h 和同名的 .cpp 文件来组织的。
1.2.3 对象的定义 一个类定义后,就可以定义该类的对象,如下面的格式:< 类名 > < 对象名列表 >类名是用户已定义过的类的标识符,对象名可以有一个或多个,多个时要用
逗号分隔。 CStuScore one, *two, three[2];
一个对象就是该对象的类所定义的成员,引用 ( 访问 ) 时可用下列方式: < 对象名 >.< 成员名 > < 对象名 >.< 成员名 >(< 参数表 >)前者表示引用数据成员,后者表示引用成员函数。“ .” 是成员运算符,用引用对象成员。 one.strName, three[0].GetAverage();对于指针对象的成员引用可用下列方式: < 对象指针名 >->< 成员名 > < 对象指针名 >->< 成员名 >(< 参数表 >)“->” 也是一个成员运算符,与“ .” 运算符的区别是:“ ->” 用来访问指针对
象的成员,而“ .” 用来访问一般对象的成员。下面的两种表示是等价的: < 对象指针名 >->< 成员名 > (*< 对象指针名 >).< 成员名 >成员函数也适用,
1.3.1 构造函数 C++ 规定:构造函数必须与相应的类同名构造函数不能指定函数返回值的类型,也不能指定为 void 类型。
class CStuScore {public:
CStuScore(char str[12]) // 第一个构造函数
{ strcpy(strName, str);}CStuScore(char str[12], char strNO[9]) // 第二个构造函数{ strcpy(strName, str);
strcpy(strStuNO, strNO);}char strName[12]; // 姓名char strStuNO[9]; // 学号 class CM
...}
1.3.1 构造函数需要说明的是:(1) 程序中的 strcpy 是 C++ 的一个库函数,用来复制字
符串,使用时需要头文件 string.h 。(2) 在类定义时,如果没有定义任何构造函数,则编译器
自动为类生成一个不带任何参数的默认构造函数。对于 CStuScore 类来说,默认构造函数的形式如下:
CStuScore( ) // 默认构造函数的形式 { }(3) 由于构造函数的参数只能在定义对象时指定,因此有: CStuScore oOne("LiMing"); 它是自动调用第一个构造函数,使得 strName 内容为“ Li
Ming” 。若有: CStuScore oTwo;
1.3.2 析构函数
析构函数也要与相应的类同名,并在名称前面加上一个“ ~” 符号。
class CStuScore{
public:...~ CStuScore ( ) { } // 析构函数...
}
析构函数只有在两种情况下才会被自动调用: (1) 当对象定义在一个函数体中,该函数调用结束后,
析构函数被自动调用。 (2) 用 new 为对象分配动态内存后,当使用 delete 释
放对象时,析构函数被自动调用。
1.3.3 对象成员初始化 为了能对这些对象成员进行初始化, C++允许采用这样的构造函数定义格式:< 类名 >::< 构造函数名 >( 形参表 ): 对象 1( 参数表 ),对象 2( 参数表 ), …, 对象 n( 参数表 )
需要说明的是 :
(1) 类的成员对象必须初始化,但不能将成员对象直接在构造函数体内进行初始化 。
(2) 对象成员初始化时,必须有相应的构造函数,且多个对象成员的构造次序不是按初始化成员列表的顺序,而是按各类声明的先后次序进行的。
(3) 成员对象初始化也可在类构造函数定义时进行。
(4) 事实上,成员初始化列表也可用于类中的普通数据成员的初始化。
1.3.4 常类型 常类型是指使用类型修饰符 const 说明的类型。常对象常对象是指对象常量,定义格式如下:< 类名 > const < 对象名 >定义常对象时,同样要进行初始化,并且该对象不能再被改变,修饰符 const 可以放在类名后面,也可以放在类名前面。
常成员函数使用 const 关键字进行声明的成员函数,称为常成员函数。只有常成员函数才有资格操作常量或常对象。常成员函数说明格式如下:< 类型说明符 > < 函数名 > (< 参数表 >) const ;
1.3.4 常类型常数据成员
类型修饰符 const 不仅可以说明成员函数,也可以说明数据成员。由于 const 类型对象必须被初始化,并且不能被改变。在类中声明 const 数据成员后,只能通过构造函数初始化方式来对常数据成员初始化 .
所谓“引用”,实质上是给一个已定义的变量起一个别名 , 系统不会为引用类型变量分配内存空间,只是使引用类型变量与其相关联的变量使用同一个内存空间。
1.3.5 this 指针 [ 例 Ex_This] this 指针的使用 #include <iostream.h>class COne{public:COne() { x = y = 0; }COne(int a, int b) {x = a; y = b; }void copy(COne &a); // 对象引用作函数参数void print() {cout<<x<<" , "<<y<<endl; }
private: int x, y;};void COne::copy(COne &
a){ if (this == &a) return; *this = a; }void main(){ COne one, two(3, 4); one.print(); one.copy(two); one.print();}
1.3.6 静态成员 静态数据成员和静态成员函数。
1. 静态数据成员 静态数所成员是同一个类中所有对象共享的成,而
不是某一对象的成员。静态数据成员始化须在类的外部进行,与一般数据成
员初始化不同,它的格式如下:< 数据类型 >< 类名 >::<静态数据成员名 >=< 值 >
2. 静态成员函数 静态成员函数和静态数据成员一样,它们都属于类的静态成员,但它们都不是对象的成员。
1.4.1 单继承 1. 公有继承 (public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。
2. 私有继承 (private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
3. 保护继承 (protected)
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
1.4.2 派生类的构造函数和析构函数 派生类对象在建立时,先执行基类的构造函数,然
后执行派生类的构造函数。 在对派生类进行初始化时,需要对其基类设置初值,
可按下列格式进行:<派生类名 >(总参表 ):<基类 1>( 参数表 1), <基类 2>
( 参数表 2), <基类 n>( 参数表 n), 对象成员 1( 对象成员参数表 1),
对象成员2( 对象成员参数表 2), …, 对象成员 n( 对象成员参数
表 n){...}
1.4.3 多继承 多继承下派生类的定义是按下面的格式:class <派生类名 > : [<继承方式 1>] <基类名 1>,[<继承方式 2>]
<基类名 2>,...{
[<派生类的成员 >]};其中的继承方式还是前面的三种: public 、 private 和 p
rotected 。例如:class A{...}class B{...}class C:public A,private B{...}
1.5.1 虚函数 [ 例 Ex_VirtualFunc] 虚函数的使
用#include <iostream.h>class CShape{public:virtual float area() // 将 area 定义成虚函数 { return 0.0; }
};class CTriangle:public CShape{public: CTriangle(float h, float w) { H=h; W=w; } float area() { return (float)(H * W * 0.5);
}private: float H, W;};
private:float H, W;
};class CCircle:public CShape{public:
CCircle(float r){ R=r; }float area(){
return (float)(3.14159265 * R * R);
}private:
float R;};void main(){
CShape *s[2];s[0] = new CTriangle(3,4);cout<<s[0]->area()<<endl;s[1] = new CCircle(5);cout<<s[1]->area()<<endl;
}
习 题 1. 定义一个描述学生基本情况的类,数据成员包括姓名,学 C++英语和数学成绩,成员函数包括输出数据、置姓名和学号、置
三门课的成绩,求出总成绩和平均成绩。2. 设有一个描述坐标点的 CPoint 类,其私有变量 x 和 y代表一个
点 的 x 、 y坐标值。编写程序实现以下功能:利用构造函数传递参 数并设其默认参数值为 60 和 75 ,利用成员函数 display 输出这
一默认的值;利用公有成员函数 setpoint 将坐标值的修改为 (80, 150) ,利用成员函数 display 输出修改后的坐标值。
3. 下面是一个类的测试程序,给出类的定义,构造一个完整的程序 执行程序时的输出为 ; 输出结果: 200 – 60 = 140 主函数为: void main() { CTest c; c.init(200, 60); c.print(); }
习 题 4. 定义一个人员类 CPerson ,包括数据成员:姓名、编号、性别和用于输入输出的成员函数。在此基础上派生出学生类 CStudent(增加成绩 ) 和教师类 CTeacher(增加教龄 ) ,并实现对学生和教师信息的输入输出。 5. 把定义平面直角坐标系上的一个点的类 CPoint 作为基类,派生出描述一条直线的类 CLine ,再派生出一个矩形类 CRect 。要求成员函数能求出两点间的距离、矩形的周长和面积等。设计一个测试程序,并构造完整的程序。
6. 定义一个字符串类 CStrOne ,包含一个存放字符串的数据成员,能够通过构造函数初始化字符串,通过成员函数显示字符串的内容。在此基础上派生出 CStrTwo 类,增加一个存放字符串的数据成员,并能通过派生类的构造函数传递参数,初始化两个字符串,通过成员函数进行两个字符串的合并以及输出。 ( 字符串合并可使用标准库函数 strcat ,需要包含头文件 string.h)
习 题7.定义一个抽象类 CShape ,包含纯虚函数 Area( 用来计算面积 ) 和 SetData( 用来重设 形状大小 ) 。然后派生出三角形 CTriangle
类、矩形 CRect 类、圆 CCircle 类,分别求 其面积。最后定义一个 CArea 类,计算这 几个形状的面积之和,各形状的数据通过 CArea 类构造函数或成员函数来设置。编 写 一个完整的程序。8. 上机练习本章的示例。