1 / 29

C++ 语言程序设计

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 :

roddy
Download Presentation

C++ 语言程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++语言程序设计 第5讲: C++程序的结构

  2. 构造函数 相当于: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: 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; } 拷贝构造函数

  3. 析构函数 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); } // 析构

  4. 构造函数可使每个对象都有正确的初始值 • 析构函数可使每个对象在结束时自动进行清理工作 • 析构函数的使用 • 一个类只能有一个析构函数,不允许重载! • 最先析构的是自动变量; • 静态对象的生命期一直到程序结束;(static) • 全局对象是最后被析构的。

  5. 访问函数和工具函数 • 将类的函数分为两大类,访问函数和工具函数。 • 访问函数是供客户调用的,一般为public。 • 工具函数是为实现访问函数的某些功能而需要的函数,一般为private。 • 数据成员和成员函数的使用 • 数据一般设为私有成员,便于保护; • 需要用户设置的私有数据成员用get和set提供给用户; • 要保证私有数据成员在任何时候都是有效的。

  6. 接口与实现的分离 • 软件工程的一个最基本的原则:接口与实现分离 • .h文件与.cpp文件分离 • 类的定义与类的实现分离 • 但是Java中类的定义与实现是在一起的,Why? • 因为Java中有一个专门管接口的类叫Interface。这个类是公开的,而其他类则被屏蔽起来。 这种方式称为对象的“包装”或称“封装”。

  7. § 控制对成员的访问 • public:, private: ( protected: ) 都是用来控制成员函数的作用。 • 类的客户可通过公有成员(public)知道类提供什么样的服务。 • 类的客户不能直接访问类的私有成员(private),它们只能通过成员函数(或友元)来访问。 • C++提倡编写与实现无关的程序。在类定义中尽量避免写函数实现的代码。(也不是绝对的,只要觉得可以公开,并以后不会改动,则可以将实现写到类的定义中) • [注意]在理论上 public:, private:protected:只使用一次。但现在C++编译器(如VC++)可支持多次。而在Java中每一个函数前面都要求加上这个说明符。

  8. §软件的可重用性 • 面向对象的程序设计的一个重要目标就是软件的可重用性。 • 可重用性意味着以前的代码可以部分加以利用,并对其余部分改写,以免整个程序重新编写。 • 要实现可重用性,程序必须设计良好、具有较好的可读性,并预先把需要扩展部分考虑好。

  9. 函数原型(prototype)的作用域 • 函数原型中的参数,其作用域仅限于声明中。 • 例如,设有下列原型声明: double Area(double radius); • radius 的作用域仅在于此,不能用于程序正文其他地方,因而可有可无。可以写成: double Area(double); • double Area(double radius=5); • 可简化成  double Area(double =5);

  10. 块作用域 • 在块中声明的标识符,其作用域自声明处起,限于块中,例如: void fun(int a) { int b(a); cin>>b; if (b>0) { int c; ...... } } a的作用域 b的作用域 c的作用域

  11. 类作用域 • 类X的成员M具有类作用域,对M的访问方式如下: • 如果在X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以访问成员M。 class X { int M; public: void fun(); } void X::fun() { M=10; { int M=20; … … } cout << M; } 类的成员变量 局部自动变量 ?

  12. 文件作用域 • 不在前述各个作用域中出现的声明,具有文件作用域,这样声明的标识符的作用域开始于声明点,结束于文件尾。 • 全局变量! int i; // 全局变量,文件作用域 void main() { i = 5; { int i;// 局部变量,块作用域 i = 7; cout << “i=“ << i << endl;// 输出 7 } cout << “i=“ << i << endl;// 输出 5 }

  13. 例5-2: 变量的生存期与可见性 #include<iostream.h> void other(); inti=1; // i 为全局变量,具有静态生存期。 int main() { static inta;// 静态局部变量,有全局寿命,局部可见。 intb= -10; // b, c为局部变量,具有动态生存期。 intc= 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(); }

  14. void other() { staticinta=2; staticintb=0; // a,b为静态局部变量,具有全局寿命,局部可见。 //只第一次进入函数时被初始化。 intc=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: 1a: 0 b: -10 c: 0 ---OTHER--- i: 33a: 4 b: 0 c: 15 ---MAIN--- i: 33a: 0 b: -10 c: 8 ---OTHER--- i: 75a: 6 b: 4 c: 15

  15. 例5-3:时钟程序 class Clock //时钟类声明 { public: //外部接口 Clock(); void SetTime(int NewH, int NewM, int NewS); // 三个形参均具有函数原型作用域 void ShowTime(); ~Clock(){} private: //私有数据成员 int Hour,Minute,Second; };

  16. //时钟类成员函数实现 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; }

  17. ClockglobClock;//声明对象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

  18. 静态成员 • 静态数据成员 • 用关键字static声明 • 该类的所有对象维护该成员的同一个拷贝 • 必须在类外定义和初始化,用(::)来指明所属的类。 • 静态成员函数 • 类外代码可以使用类名和作用域操作符来调用静态成员函数。 • 静态成员函数只能引用属于该类的静态数据成员或静态成员函数。

  19. 静态数据成员声明 例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; staticint countP; };

  20. 静态数据成员初始化 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(); }

  21. 静态成员函数举例 class Application { public: staticvoid f(); staticvoid g(); private: staticint global; }; int Application::global=0; void Application::f() { global = 5; } void Application::g() { cout << global << endl; } int main() { Application::f(); Application::g(); return 0; }

  22. 友元 friend • 友元是C++提供的一种破坏数据封装和数据隐藏的机制。 • 通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息。 • 可以使用友元函数和友元类。 • 为了确保数据的完整性,及数据封装与隐藏的原则,建议尽量不使用或少使用友元。

  23. 例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; } friendfloat 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; }

  24. class A { friend class B; public: void Display() { cout << x << endl; } private: int x; } classB { public: void Set(int i); void Display(); private: A a; }; voidB::Set(int i) { a.x = i; } voidB::Display() { a.Display(); } 友元类 访问A的私有成员 但在 A 中不能访问 B 的私有成员。!!!

  25. 常类型 const • 常类型是只读的意思。 • 常类型的对象必须进行初始化,而且不能被更新。 • 常引用:被引用的对象不能被更新。 const 类型说明符 &引用名 • 常对象:必须进行初始化,不能被更新。 类名 const 对象名

  26. 常对象举例 class A { public: A(int i,int j) { x = i; y = j; } ... private: int x,y; }; A const a(3,4); //a是常对象,不能被修改

  27. 例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 }

  28. 例5-9: 常数据成员举例 int main() {/*建立对象a和b,并以100和0作为初值, 分别调用构造函数,通过构造函数的初始化 列表给对象的常数据成员赋初值*/ A a1(100),a2(0); a1.print(); a2.print(); } class A {public: A(int i); void print(); constint& r; private: constint a; staticconstintb; //静态常数据成员 }; constint A::b=10; A::A(int i): a(i), r(a) {} void A::print() { cout<<a<<":"<<b<<":"<<r<<endl; } 运行结果: 100:10:100 0:10:0

More Related