29
C++ 语语语语语语 语5语C++ 语语语语语

C++ 语言程序设计

  • Upload
    roddy

  • View
    132

  • Download
    3

Embed Size (px)

DESCRIPTION

C++ 语言程序设计. 第 5 讲: C++ 程序的结构. 构造函数. 相当于: Clock::Clock() { hour = minute = second = 0; }. 默认参数构造函数. class Clock { public : Clock() : hour(0), minute(0), second(0) {} Clock( int NewH, int NewM=0, int NewS=0); Clock(Clock& c); private : - PowerPoint PPT Presentation

Citation preview

Page 1: C++ 语言程序设计

C++ 语言程序设计

第 5 讲: C++ 程序的结构

Page 2: C++ 语言程序设计

构造函数class Clock {

public: Clock() : hour(0), minute(0), second(0) {} Clock(int NewH, int NewM=0, int NewS=0); Clock(Clock& c);private: int hour; int minute; int second;};

Clock::Clock(int NewH, int NewM, int NewS){ hour = NewH; minute = NewM; second = NewS;}Clock::Clock(Clock& c){ hour = c.hour; minute = c.minute; second = c.second;}

相当于: Clock::Clock() { hour = minute = second = 0; }

拷贝构造函数默认参数构造函数

Page 3: C++ 语言程序设计

析构函数class Clock {

public:

Clock();

void SetTime (int, int, int);

void ShowTime();

~Clock(); // 析构函数private:

int hour; int minute; int second;

char* pbuf;

};

Clock::Clock() { pbuf = new char[128]; }

Clock::~Clock() { delete[] pbuf; }

对象被删除的时刻自动调用

main()

{

Clock c; // 构造

c.SetTime(9,30,30);

} // 析构

Page 4: C++ 语言程序设计

构造函数可使每个对象都有正确的初始值

析构函数可使每个对象在结束时自动进行清理工作

析构函数的使用 一个类只能有一个析构函数,不允许重载! 最先析构的是自动变量; 静态对象的生命期一直到程序结束;( static ) 全局对象是最后被析构的。

Page 5: C++ 语言程序设计

访问函数和工具函数 将类的函数分为两大类,访问函数和工具函数。 访问函数是供客户调用的,一般为 public 。 工具函数是为实现访问函数的某些功能而需要的

函数,一般为 private 。

数据成员和成员函数的使用 数据一般设为私有成员,便于保护; 需要用户设置的私有数据成员用 get 和 set 提供

给用户; 要保证私有数据成员在任何时候都是有效的。

Page 6: C++ 语言程序设计

接口与实现的分离软件工程的一个最基本的原则:接口与实现

分离 .h 文件与 .cpp 文件分离 类的定义与类的实现分离

但是 Java中类的定义与实现是在一起的, Why?

因为 Java中有一个专门管接口的类叫Interface。这个类是公开的,而其他类则被屏蔽起来。

这种方式称为对象的“包装”或称“封装”。

Page 7: C++ 语言程序设计

public:, private: ( protected: ) 都是用来控制成员函数的作用。

类的客户可通过公有成员 (public) 知道类提供什么样的服务。

类的客户不能直接访问类的私有成员 (private) ,它们只能通过成员函数(或友元)来访问。

C++ 提倡编写与实现无关的程序。在类定义中尽量避免写函数实现的代码。(也不是绝对的,只要觉得可以公开,并以后不会改动,则可以将实现写到类的定义中)

[ 注意 ] 在理论上 public:, private: protected: 只使用一次。但现在 C++ 编译器(如 VC++) 可支持多次。而在 Java 中每一个函数前面都要求加上这个说明符。

§ 控制对成员的访问

Page 8: C++ 语言程序设计

§ 软件的可重用性 面向对象的程序设计的一个重要目标就是软件的可重用性。

可重用性意味着以前的代码可以部分加以利用,并对其余部分改写,以免整个程序重新编写。

要实现可重用性,程序必须设计良好、具有较好的可读性,并预先把需要扩展部分考虑好。

Page 9: C++ 语言程序设计

函数原型( prototype )的作用域 函数原型中的参数,其作用域仅限于声明中。 例如,设有下列原型声明:

double Area(double radius); radius 的作用域仅在于此,不能用于程序正文其他地方,因而

可有可无。可以写成:

   double Area(double);

double Area(double radius=5); 可简化成  double Area(double =5);

Page 10: C++ 语言程序设计

块作用域 在块中声明的标识符,其作用域自声明处起,

限于块中,例如:void fun(int a){ int b(a);

cin   >>   b; if (b>0) { int c; ...... }}

a 的作用域

b 的作用域

c 的作用域

Page 11: C++ 语言程序设计

类作用域 类 X 的成员 M 具有类作用域,对 M 的访问方式

如下: 如果在 X 的成员函数中没有声明同名的局部作用域标

识符,那么在该函数内可以访问成员 M 。class X { int M; public: void fun(); }void X::fun(){ M=10; { int M=20; … … } cout << M;}

局部自动变量

类的成员变量

Page 12: C++ 语言程序设计

文件作用域 不在前述各个作用域中出现的声明,具有文件

作用域,这样声明的标识符的作用域开始于声明点,结束于文件尾。

全局变量!int i;       // 全局变量,文件作用域void main()

{ i = 5;

{ int i;    // 局部变量,块作用域 i = 7;

cout << “i=“ << i << endl;    // 输出 7 }

cout << “i=“ << i << endl;     // 输出 5}

Page 13: C++ 语言程序设计

例 5-2 : 变量的生存期与可见性#include<iostream.h>void other();

int i=1; // i 为全局变量,具有静态生存期。int main()

{ static int a;// 静态局部变量,有全局寿命,局部可见。 int b = -10; // b, c 为局部变量,具有动态生存期。 int c = 0;  cout <<"---MAIN---\n";

cout <<" i: "<< i <<" a: "<< a <<" b: "<< b << " c: "   <<   c   <<   endl;

c = c+8; other(); cout <<"---MAIN---\n";

cout <<" i: "<< i <<" a: "<< a <<" b: "<< b <<" c: " << c << endl;

i=i+10; other(); }

Page 14: C++ 语言程序设计

void other(){

static int a=2; static int b=0; // a,b 为静态局部变量,具有全局寿命,局部可见。 // 只第一次进入函数时被初始化。 int c=10; // C 为局部变量,具有动态生存期, // 每次进入函数时都初始化。 a=a+2; i=i+32; c=c+5; cout<<"---OTHER---\n";

cout<<" i: "<< i <<" a: "<< a <<" b: "<< b <<" c: " << c << endl; b=a;}

运行结果:---MAIN---

i: 1 a: 0 b: -10 c: 0

---OTHER---

i: 33 a: 4 b: 0 c: 15

---MAIN---

i: 33 a: 0 b: -10 c: 8

---OTHER---

i: 75 a: 6 b: 4 c: 15

Page 15: C++ 语言程序设计

例 5-3 :时钟程序class Clock // 时钟类声明{

public: // 外部接口Clock();

void SetTime(int NewH, int NewM, int NewS); // 三个形参均具有函数原型作用域void ShowTime();

~Clock(){}

private: // 私有数据成员int Hour,Minute,Second;

};

Page 16: C++ 语言程序设计

// 时钟类成员函数实现Clock::Clock() // 构造函数{ Hour=0;Minute=0;Second=0;

}void Clock::SetTime(int NewH,int NewM,int NewS){ Hour=NewH;Minute=NewM;Second=NewS;

}void Clock::ShowTime(){cout<<Hour<<":"<<Minute<<":"<<Second<<endl;

}

Page 17: C++ 语言程序设计

Clock globClock;// 声明对象 globClock , // 具有静态生存期,文件作用域int main() // 主函数{

cout<<"First time output:"<<endl;

// 引用具有文件作用域的对象:globClock.ShowTime();// 对象的成员函数具有类作用域globClock.SetTime(8,30,30);

Clock myClock(globClock);

// 声明具有块作用域的对象 myClock

cout<<"Second time output:"<<endl;

myClock.ShowTime(); // 引用具有块作用域的对象}

程序的运行结果为:First time output:

0:0:0

Second time output:

8:30:30

Page 18: C++ 语言程序设计

静态成员静态数据成员

用关键字 static 声明 该类的所有对象维护该成员的同一个拷贝 必须在类外定义和初始化,用 (::) 来指明

所属的类。静态成员函数

类外代码可以使用类名和作用域操作符来调用静态成员函数。

静态成员函数只能引用属于该类的静态数据成员或静态成员函数。

Page 19: C++ 语言程序设计

例 5-4 : 具有静态数据成员的 Point类class Point{public:Point(int xx=0, int yy=0)

{ X=xx; Y=yy; countP++; } Point(Point &p);int GetX(){return X;}int GetY(){return Y;}void GetC()

{ cout <<" Object id = " << countP << endl; } private:int X,Y;static int countP;

};静态数据成员声明

Page 20: C++ 语言程序设计

Point::Point(Point &p){ X=p.X;Y=p.Y;countP++;

}

int Point::countP=0; int main(){ Point A(4,5);cout<<"Point A,"<<A.GetX()<<","<<A.GetY();A.GetC();Point B(A);cout<<"Point B,"<<B.GetX()<<","<<B.GetY();B.GetC();

}

静态数据成员初始化

Page 21: C++ 语言程序设计

静态成员函数举例class Application{ public: static void f(); static void g(); private: static int global;};

int Application::global=0;

void Application::f(){ global = 5; }

void Application::g(){ cout << global << endl; }

int main(){ Application::f(); Application::g(); return 0;}

Page 22: C++ 语言程序设计

友元 friend友元是 C++ 提供的一种破坏数据封装和数

据隐藏的机制。通过将一个模块声明为另一个模块的友元,

一个模块能够引用到另一个模块中本是被隐藏的信息。

可以使用友元函数和友元类。为了确保数据的完整性,及数据封装与隐藏的原则,建议尽量不使用或少使用友元。

Page 23: C++ 语言程序设计

例 5-6 : 使用友元函数计算两点距离class Point //Point 类声明{ public:   // 外部接口

   Point(int xx=0, int yy=0) {X=xx;Y=yy;}   int GetX() { return X; }   int GetY() { return Y; }friend float fDist (Point &a, Point &b);

private:   // 私有数据成员   int X,Y;

};float fDist ( Point& a, Point& b ){ double dx = a.X-b.X; double dy = a.Y-b.Y; return (float)sqrt(dx*dx+dy*dy);}

int main(){ Point myp1(1.0f, 1.0f), myp2(4.0f, 5.0f); cout<<"The distance is “; cout<< fDist (myp1, myp2) << endl; return 0;}

Page 24: C++ 语言程序设计

友元类class A{ friend class B; public: void Display() { cout << x << endl; } private: int x;}

class B{ public: void Set(int i); void Display(); private: A a;};

void B::Set(int i)

{

a.x = i;

}

void B::Display()

{

a.Display();

}

访问 A 的私有成员

但在 A 中不能访问 B 的私有成

员。 !!!

Page 25: C++ 语言程序设计

常类型  const

常类型是只读的意思。常类型的对象必须进行初始化,而且不能

被更新。常引用:被引用的对象不能被更新。

const 类型说明符 & 引用名常对象:必须进行初始化 , 不能被更新。

类名 const 对象名

Page 26: C++ 语言程序设计

常对象举例class A

{

public:

A(int i,int j) { x = i; y = j; }

...

private:

int x,y;

};

A const a(3,4); //   a 是常对象,不能被修改

Page 27: C++ 语言程序设计

例 5-8 : 常成员函数举例class R

{ public:

R(int r1, int r2){ R1 = r1; R2 = r2; }

void print();

void print() const;

private:

int R1,R2;

};

void R::print()

{ cout<<R1<<":"<<R2<<endl;

}

void R::print() const

{ cout<<R1<<";"<<R2<<endl;

}

int main(){ R a(5,4); a.print();

// 调用 void print() const R b(20,52); b.print();

// 调用 void print() const}

Page 28: C++ 语言程序设计

例 5-9 : 常数据成员举例class A{public:

A(int i);void print();const int& r;

private:const int a;static const int b; // 静态常数据成员

};

const int A::b=10; A::A(int i): a(i), r(a) {}void A::print(){ cout<<a<<":"<<b<<":"<<r<<endl; }

int main()

{/* 建立对象 a 和 b ,并以 100 和 0 作为初值,分别调用构造函数,通过构造函数的初始化列表给对象的常数据成员赋初值 */

A a1(100),a2(0);

a1.print();

a2.print();

}

运行结果:

100:10:100

0:10:0

Page 29: C++ 语言程序设计