类的设计练习

类名:圆
属性:半径。
行为:设半径值;求面积;求周长。
面向对象程序设计
Circle类的定义和描述;
没有空间,不能直接使用;
必须进行实例化,即定义对象

class Circle{
   
private:
double radius;
public:
void setRadius(double r)
{
    radius=r; }
double getArea()
{
    return 3.14159*radius*radius; }
double getPerimeter()
{
    return 3.14159*2*radius; }
};
int main()
{
   
Circle c1;
c1.setRadius(1.5);
cout<<“半径为”<<c1.getRadius()<<<<“的圆周 长是"<<c1.getPerimeter()<<endl;
cout<<"半径为"<<c1.getRadius()<<<<"的圆面积是"<<c1.getArea()<<endl;
}

以前的思路

#include<iostream>
using namespace std;
const double PI=3.14159;
int main()
{
   
double r,s,d;
cout<<"请输入圆的半径:";
cin>>r;
d=2*PI*r;
s=PI*r*r;
cout<<"半径为"<<r<<"的圆周长是
<<d<<endl;
cout<<"半径为"<<r<<"的圆面积是
<<s<<endl;
return 0;
}

同类题目

求半径分别为5和3组成的圆环
的面积和周长

int main()
{
   
Circle cBig,cSmall;
cBig.setRadius(5);
cSmall.setRadius(3)
cout<<“圆环的周长是"<<cBig.getPerimeter()+cSmall.getPerimeter()<<endl;
cout<<“圆环的面积是"<<cBig.getArea()-cSmall.getArea()<<endl;
}

类的深入剖析

Time类

+setTime(int,int,int);
+printStandard();
+printUniversal();
Time
-hour : int
-minute :int
-second :int
类名:Time
属性:时,分,秒。
行为:设时间;24小时制输出
时间;12小时制输出时间。

class Time 
{
   
public:
void setTime( int h, int m, int s )
{
    hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour
minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute
second = ( s >= 0 && s < 60 ) ? s : 0; // validate second
} 
void printUniversal() // print Time in universal-time format (HH:MM:SS)
{
    cout << setfill( '0' ) << setw( 2 ) << hour << ":" 
<< setw( 2 ) << minute << ":" << setw( 2 ) << second;
}
void printStandard() // print Time in standard-time format (HH:MM:SS AM or PM)
{
    cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" 
<< setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 )
<< second << ( hour < 12 ? " AM" : " PM" );
private:
int hour; // 0 - 23 (24-hour clock format)
int minute; // 0 - 59
int second; // 0 - 59
}; // end class Time
int main()
{
   
Time t; // instantiate object t of class Time
t.setTime( 13, 27, 6 ); // change time
cout << "\n\nUniversal time after setTime is ";
t.printUniversal(); // 13:27:06
cout << "\nStandard time after setTime is ";
t.printStandard(); // 1:27:06 PM
t.setTime( 99, 99, 99 ); // attempt invalid settings
// output t's values after specifying invalid values
cout << "\n\nAfter attempting invalid settings:"
<< "\nUniversal time: ";
t.printUniversal(); // 00:00:00
cout << "\nStandard time: ";
t.printStandard(); // 12:00:00 AM
cout << endl;
return 0; 
}

类的相关概念

private :私有访问权限,是类成员的默认成员访问说明符 。
private成员只能被类的成员函数访问。私有权限设置为了实现数据隐藏
public :公有访问权限。
public成员能被对象外函数直接访问。公有权限提供了外部访问对象的接口。

类的使用

类是概念的抽象和描述,没有空间,需要通过实例化才能使用,即定义对象Time t;

关于对象

定义对象后,可通过 对象名.成员名的方式直接访问对象的公有成员。
Time t;
t.setTime(13,30,1);
或者
Time t;
Time &t1=t;
t1.setTime(13,30,1);
或者
Time t;
Time *pt=&t;
Pt->setTime(13,30,1);

public 类成员可以通三种句柄来引用
对象名 对象名.成员
对象引用 对象引用.成员
对象指针 对象指针->成员

对象的私有成员必须通过公有成员函数才能访问

类的设计和信息隐藏

类的实现细节应该对客户不可见,这叫做信息隐藏。
客户端代码可以通过类提供的公有成员函数接口访问对象的内部数据。
类的定义,包括成员数据定义和成员函数原型说明,单独保存为头文件(time.h)
类的实现,包括所有成员函数的具体实现,保存为与头文件同名的cpp源文件(time.cpp)
类的实现源文件中所有的成员函数均为类外定义,需要:
1)包含同名头文件;
2)在每个函数名前加类名前缀
time.h

// Time class definition
class Time 
{
   
public:
void setTime( int, int, int ); // set hour, minute and second
void printUniversal(); // print time in universal-time format
void printStandard(); // print time in standard-time format
private:
int hour; // 0 - 23 (24-hour clock format)
int minute; // 0 - 59
int second; // 0 - 59
}; // end class Time

time.cpp

#include <iostream>
#include <iomanip>
using namespace std;
#include "Time.h" // include definition of class Time from 
Time.h
void Time::setTime( int h, int m, int s )
{
   
hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour
minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute
second = ( s >= 0 && s < 60 ) ? s : 0; // validate second
} // end function setTime

mainTime.cpp

#include <iostream>
#include <iomanip>
using namespace std;
#include "Time.h" // include definition of class Time from Time.h
int main()
{
   
Time t; // instantiate object t of class Time
t.setTime( 13, 27, 6 ); // change time
cout << "\n\nUniversal time after setTime is ";
t.printUniversal(); // 13:27:06
cout << "\nStandard time after setTime is ";
t.printStandard(); // 1:27:06 PM
}

Time类的多文件实现


在time.cpp文件和mainTime.cpp文件中都因为需要出现了包含“time.h”的预处理语句。这种情况会导致头文件中的代码被多次包含到同一个源文件中,引发重复定义的错误。可通过使用预处理封套来解决这个问题。
头文件名用大写形式
头文件名中圆点(.)换成下划线

#ifndef TIME_H
#define TIME_H

class Time 
{
   
public:
void setTime( int, int, int ); 
void printUniversal(); 
void printStandard(); 
private:
int hour; 
int minute;
int second;
}; 

#endif

对象的初始化

构造函数

构造函数是一个特殊的成员函数,它与类同名无返回值。在定义对象时由系统自动调用,主要用于初始化成员数据。构造函数的函数实现主要是对成员数据的赋值,根据不同的需要,构造函数可以:
——定义参数表,函数体中用参数对数据成员赋值
——缺省参数表,函数体重用特定的固定值对数据成员赋值。
未显式定义构造函数时,系统会自动生成一个缺省参数的构造函数,函数实现为

1 // Fig. 9.1: Time.h 
2 // Declaration of class Time. 
3 // Member functions are defined in Time.cpp 
4
5 // prevent multiple inclusions of header file 
6 #ifndef TIME_H 
7 #define TIME_H 
8
9 // Time class definition 
10 class Time 
11 {
    
12 public: 
13 Time(); // constructor 
14 void setTime( int, int, int ); // set hour, minute and second 
15 void printUniversal(); // print time in universal-time format 
16 void printStandard(); // print time in standard-time format 
17 private: 
18 int hour; // 0 - 23 (24-hour clock format) 
19 int minute; // 0 - 59 
20 int second; // 0 - 59 
21 }; // end class Time 
22
23 #endif 
1 // Fig. 9.2: Time.cpp 
2 // Member-function definitions for class Time. 
3 #include <iostream> 
4 #include <iomanip> 
5 #include <stdexcept>
6 #include "Time.h" // include definition of class Time from Time.h 
7 
8 using namespace std; 
9
10 // Time constructor initializes each data member to zero. 
11 Time::Time()
12 : hour( 0 ), minute( 0 ), second( 0 ) 
13 {
    
14 }// end Time constructor 
15 
16 // set new Time value using universal time; ensure that 
17 void Time::setTime( int h, int m, int s ) 
18 {
   
19 // validate hour, minute and second 
20 if ( ( h >= 0 && h < 24 ) && ( m >= 0 && m < 6 0 ) && 
21 ( s >= 0 && s < 60 ) 
22 {
    
23 hour = h; 
24 minute = m; // validate minute 
25 second = s; // validate second 
26 } // end if
27 else
28 throw invalid_argument(
29 “hour,minute and/or second was out of range”)
30 }//end function setTime

异常与抛出异常

异常:程序运行时发生的反常行为(运行中断,报错)
异常处理:检测并处理异常
*异常处理不是“消灭”异常,而是积极获取异常的处理主动权

构造函数——带参数的构造函数


构造函数 析构函数

对象与变量也有作用域和生命期的限定。
生命期开始——分配对象空间,隐式调用构造函数;
生命期结束——撤销对象空间,隐式调用析构函数

析构函数在系统回收对象所占用的内存空间之前做一些清理、扫尾工作。
析构函数的名字同类名,并在前面加“~”字符,用来与构造函数加以区别。析构函数没有返回值,并且也没有参数。
析构函数不能重载,如果用户未定义,系统会自动生成“空的”析构函数。

1 // Fig. 9.11: CreateAndDestroy.h 
2 // Definition of class CreateAndDestroy. 
3 // Member functions defined in CreateAndDestroy.cpp. 
4 #include <string> 
5 using std::string; 
6
7 #ifndef CREATE_H 
8 #define CREATE_H 
9
10 class CreateAndDestroy 
11 {
    
12 public: 
13 CreateAndDestroy( int, string ); // constructor 
14 ~CreateAndDestroy(); // destructor 
15 private: 
16 int objectID; // ID number for object 
17 string message; // message describing object 
18 }; // end class CreateAndDestroy 
19
20 #endif 

析构函数定义

1 // Fig. 9.12: CreateAndDestroy.cpp 
2 // Member-function definitions for class CreateAndDestroy. 
3 #include <iostream> 
4 using std::cout; 
5 using std::endl; 
6
7 #include "CreateAndDestroy.h"// include CreateAndDestroy class definition 
8 
9 // constructor 
10 CreateAndDestroy::CreateAndDestroy( int ID, string messageString )
11 {
    
12 objectID = ID; // set object's ID number 
13 message = messageString; // set object's descriptive message 
14 
15 cout << "Object " << objectID << " constructor runs " 
16 << message << endl; 
17 } // end CreateAndDestroy constructor 
18
19 // destructor 
20 CreateAndDestroy::~CreateAndDestroy() 
21 {
    
22 // output newline for certain objects; helps readability 
23 cout << ( objectID == 1 || objectID == 6 ? "\n" : "" ); 
24 
25 cout << "Object " << objectID << " destructor runs " 
26 << message << endl; 
27 } // end ~CreateAndDestroy destructor

全局范围中定义的对象的构造函数在文件中的任何其他函数(包括main)执行之前调用
当程序执行到对象定义时,调用自动局部对象的构造函数
局部静态对象在main函数中调用构造函数

1 // Fig. 9.13: fig09_13.cpp 
2 // Demonstrating the order in which constructors and 
3 // destructors are called. 
4 #include <iostream> 
5 using std::cout; 
6 using std::endl; 
7
8 #include "CreateAndDestroy.h" // include CreateAndDestroy class definition 
9
10 void create( void ); // prototype 
11
12 CreateAndDestroy first( 1, "(global before main)" ); // global object 
13
14 int main() 
15 {
    
16 cout << "\nMAIN FUNCTION: EXECUTION BEGINS" << endl; 
17 CreateAndDestroy second( 2, "(local automatic in main)" ); 
18 static CreateAndDestroy third( 3, "(local static in main)" );
19 
20 create(); // call function to create objects 
21
22 cout << "\nMAIN FUNCTION: EXECUTION RESUMES" << endl; 
23 CreateAndDestroy fourth( 4, "(local automatic in main)" );
24 cout << "\nMAIN FUNCTION: EXECUTION ENDS" << endl; 
25 return 0; 
26 } // end main
27 
28 // function to create objects 
29 void create( void ) 
30 {
    
31 cout << "\nCREATE FUNCTION: EXECUTION BEGINS" << endl; 
32 CreateAndDestroy fifth( 5, "(local automatic in create)" ); 
33 static CreateAndDestroy sixth( 6, "(local static in create)" );
34 CreateAndDestroy seventh( 7, "(local automatic in create)" ); 
35 cout << "\nCREATE FUNCTION: EXECUTION ENDS" << endl; 
36 } // end function create

static局部对象的构造函数只在程序执行首次到达对象定义时调用一次,对应的析构函数在main终止时调用
自动对象的构造函数与析构函数在每次对象进人和离开范围时调用
析构函数的调用顺序与构造函数相反

作业

P76 3.15
参考Time类的实现,考虑有效性检测和对应的异常处理
3.15实现代码

P76 3.17
尽可能完善输出信息
参考给定的参考资料,实现自动计算用户年龄
3.17实现代码

P322 9.15
9.15实现代码