370 likes | 523 Views
类和对象及其封装性. 回顾:面向对象的方法. 目的: 实现软件设计的产业化。 观点: 自然界是由实体(对象)所组成。 程序设计方法: 使用面向对象的观点来描述模仿并处理现实问题。 要求: 高度概括、分类、和抽象。. 抽象. 抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程。 先注意问题的本质及描述,其次是实现过程或细节。 数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)。 代码抽象:描述某类对象的共有的行为特征或具有的功能。 抽象的实现:通过类的声明。. 抽象实例——钟表. 数据抽象:
E N D
回顾:面向对象的方法 • 目的: • 实现软件设计的产业化。 • 观点: • 自然界是由实体(对象)所组成。 • 程序设计方法: • 使用面向对象的观点来描述模仿并处理现实问题。 • 要求: • 高度概括、分类、和抽象。
抽象 抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程。 • 先注意问题的本质及描述,其次是实现过程或细节。 • 数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)。 • 代码抽象:描述某类对象的共有的行为特征或具有的功能。 • 抽象的实现:通过类的声明。
抽象实例——钟表 • 数据抽象: int Hour, int Minute, int Second • 代码抽象: SetTime(), ShowTime()
抽象实例——钟表类 class Clock { public: void SetTime(int NewH, int NewM, int NewS); void ShowTime(); private: int Hour,Minute,Second; };
抽象实例——人 • 数据抽象: char *name,char *sex,int age,int id • 代码抽象: 生物属性角度:GetCloth(), Eat(), Step(),… 社会属性角度:Work(), Promote() ,…
封装 将抽象出的数据成员、代码成员相结合,将它们视为一个整体。 • 目的是曾强安全性和简化编程,使用者不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。 • 实现封装:类声明中的{}
外部接口 边界 封装 • 实例: class Clock { public: void SetTime(int NewH,int NewM, int NewS); void ShowTime(); private: int Hour,Minute,Second; }; 特定的访问权限
类与对象的声明和定义 1. 类的定义 类的定义: • 成员函数的定义 • 数据成员的定义
2、声明类的一般形式为 class 类名 { private: 私有数据和函数 public: 公有数据和函数 protected: 保护数据和函数 };
3、说明 (1)类声明以关键字class开始,其后跟类名。 (2)类所声明的内容用花括号括起来,这一对花括号“{ }”之间的内容称为类体。 (3)类中定义的数据和函数分别是数据成员和成员函数
4、访问权限 (1)用于控制对象的某个成员在程序中的可访问性 (2)关键字private 、public和protected 定义的成员访问权限分别是私有、公有和保护的,把这些成员分别叫做私有成员、公有成员和保护成员 (3)所有成员默认声明为private权限。
例: 定义一个Person类 class Person {private: char Name[20]; int Age; char Sex; public: void Register(char *name, int age, char sex); void ShowMe(); };
成员函数的定义 返回类型 类名∷成员函数名(参数列表) { 成员函数的函数体//内部实现 } 其中“∷”是作用域运算符,“类名”是成员函数所属类的名字,“∷”用于表明其后的成员函数是属于这个特定的类。换言之,“类名∷成员函数名”的意思就是对属于“类名”的成员函数进行定义,而“返回类型”则是这个成员函数返回值的类型。余下的工作就是定义成员函数的函数体。
二、对象的定义 定义格式: <类名> <对象1>,<对象2>,… ; 例如:Person person1,person2;
3 成员函数 一、成员函数的定义 格式:<类型> <类名>::<函数名>(<参数表>) { <函数体> } 二、内联成员函数 使用关键字inline将成员函数定义为内联函数 例如: inline void Person:: Register(char *name, int age, char sex) {……;}
例: Person类成员函数的定义 void Person:: Register(char *name, int age, char sex) { strcpy(Name, name); Age = age; Sex = (sex == 'm'? 'm':‘f'); } void Person:: ShowMe() { cout << Name << '\t' << Age << '\t' << Sex << endl; }
4 对象的访问 1、在类的作用域内,成员函数直接访问同类中的数据成员 2、在类的作用域外,访问对象数据成员或成员函数需使用运算符“.” 3、在类的作用域外,禁止直接访问一个对象中的私有成员 4、同类对象之间可以整体赋值 5、对象用作函数的参数时属于赋值调用; 6、函数可以返回一个对象
例 :完整的人事资料输入输出程序 int main() { char name[20], sex; int age; Person person1, person2; cout << "Enter a person's name, age and sex:"; cin >> name >> age >> sex; person1.Register(name, age, sex);
cout << "person1: \t"; person1.ShowMe(); //调用类的成员函数输出 person1.Register("Zhang3", 19, 'm'); cout << "person1: \t"; person1.ShowMe(); //调用类的成员函数输出 person2 = person1; //对象之间的赋值 cout << "person2: \t"; person2.ShowMe(); //调用类的成员函数输出 return 0; }
例: 简单的日期类 定义一个最简单的日期类,仅包含说明日期的数据成员。 // Example : 最简单的日期类 #include <iostream> using namespace std; class Date { public: int day, month, year; };
int main() { Date date1, date2; //声明2个日期对象 cin >> date1.day >> date1.month >> date1.year; cout << date1.month << “-“ << date1.day << “-“ << date1.year << endl; cin >> date2.day >> date2.month >> date2.year; cout << date2.month << “-“ << date2.day << “-“ << date2.year << endl; return 0; }
例: 定义最简单的日期类,用函数实现对象的输入输出操作。 #include <iostream> using namespace std; class Date { public: int day, month, year; }; void set_date(Date& d); void show_date(Date d);
void set_date(Date& d) { cin >> d.day >> d.month >> d.year; } void show_date(Date d) { cout << d.month << "-" << d.day << "-" << d.year << endl; }
int main() { Date date1, date2; //声明2个日期对象 set_date(date1); //使用全局函数操作数据成员 show_date(date1); set_date(date2); show_date(date2); return 0; }
例定义简单的完整意义上的日期类 #include <iostream> using namespace std; class Date { int day, month, year; public: void init(int,int,int); //初始化数据成员 void print_ymd(); void print_mdy(); };
void Date::init(int yy, int mm, int dd) { month = ( mm >= 1 && mm <= 12 ) ? mm : 1; year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900; day = ( dd >= 1 && dd <= 31 ) ? dd : 1; } void Date::print_ymd() { cout << year << "-" << month << "-" << day << endl;} void Date::print_mdy() { cout << month << "-" << day << "-" << year << endl;}
int main() { Date date1,date2; date1.print_ymd(); //未初始化时的情况 date1.init(2006,3,28); //正确的初始化数据 date1.print_ymd(); date1.print_mdy(); date2.init(2006,13,38); //错误的初始化数据 date2.print_ymd(); date2.print_mdy(); return 0; }
程序设计举例 • 点类和圆类 • 在二维平面空间上,使用(x,y)坐标可以确定一个点,确定了圆心坐标和半径可以确定一个圆。声明一个点类,并使用这个点类的对象为数据成员声明圆类。
// Point.h文件 Point类的声明 #ifndef POINT_H #define POINT_H class Point { int x, y; //点的x和y坐标 public: void SetPoint( int, int ); // 设置坐标 int GetX() { return x; } // 取x坐标 int GetY() { return y; } // 取y坐标 void Print(); //输出点的坐标 }; #endif
// Point.cpp文件 Point类的成员函数定义 #include <iostream> using namespace std; #include "point.h" void Point::SetPoint( int a, int b ) { x = a; y = b; } void Point::Print() { cout << '[' << x << ", " << y << ']';}
// Circle.h文件 Circle类的声明 #ifndef CIRCLE_H #define CIRCLE_H #include <iostream> using namespace std; #include "point.h" class Circle { double Radius; Point Center;
public: void SetRadius(double); //设置半径 void SetCenter(Point); //设置圆心坐标 double GetRadius(); //取半径 Point GetCenter(); //取圆心 double Area(); //计算面积 void Print(); //输出圆心坐标和半径 }; #endif
// Circle.cpp文件 Circle类的成员函数定义 #include <iostream> using namespace std; #include "circle.h" void Circle::SetRadius(double r) { Radius = ( r >= 0 ? r : 0 ); } void Circle::SetCenter(Point p) { Center = p; } Point Circle::GetCenter() { return Center; }
double Circle::GetRadius() { return Radius; } double Circle::Area() { return 3.14159 * Radius * Radius; } void Circle::Print() { cout << "Center = "; Center.Print(); cout << "; Radius = " << Radius << endl; }
// Example.cpp文件: Circle Demo #include <iostream> using namespace std;#include "point.h" #include "circle.h" int main() { Point p,center; p.SetPoint(30,50); center.SetPoint(120,80); Circle c; c.SetCenter(center); c.SetRadius(10.0);
cout << "Point p: "; p.Print(); cout << "\nCircle c: "; c.Print(); cout << "The centre of circle c: "; c.GetCenter().Print(); cout << "\nThe area of circle c: " << c.Area() << endl; return 0; }