目录
5、重载成员函数(Overloading Member Functions)
8、常成员函数(Const Member Functions)
一、面向对象的思想、方法
(一)面向对象的思想
客观世界是由各种各样的对象构成的,每种对象都有各自的属性和行为,不同对象之间的相 互作用和联系构成了不同的系统。
(二)面向对象的方法
就是要面对现实世界的实体,以对象为基本单位,分析、设计和实现一个系统。
(三)面向对象的程序设计
支持抽象及封装、继承和多态性。封装使对象的内部实现与外界隔离,提供了更理想的模块化 机制,减少了程序间的互相干扰;继承使得软件具有高度 可重用性;多态性使得编程方法更易扩充,从而大大提高了程序的开发效率。
二、面向对象的基本概念
对象
对象指现实世界中无所不在的各式各样的 实体,每一个实体都有其一些特定的属性和行为, 在面向对象的程序设计中将该实体的属性(数据) 和行为(操作数据的函数)封装在一个整体里; 每一个实体都有一个所属的类,在该类中还有许 多其他的不同实体,因此在建立对象时,必须给 对象赋予唯一的标识符,用来标识该对象。
类
是对一组对象共同具有的属性和行为进行 的抽象
三、面向对象程序设计的特点
a. 封装 封装是指将抽象得到的数据和代码集合在一个整体 里的过程,具有对内部细节隐藏保护的能力,封装保证了 类具有较好的独立性,防止外部程序破坏类的内部数据, 便于程序的维护和修改。
b. 继承 继承者拥有被继承者所有的相关属性及行为,同时 又可以增加自身新的特性。继承增强了代码的可重用性, 大大提高了软件的开发效率和系统的可靠性。
c. 多态性 多态性是指发出同样的消息被不同类型的对象接 收时导致完全不同的行为,即当向不同的对象发出相同的 服务请求时,会得到不同的响应。具有多态性的表现为: 支持函数重载;支持运算符重载;支持虚函数和动态联编。
四、类及定义一个类
(一)用一个日期类理解从结构到类
1、定义一个日期结构
例:定义一个日期型结构变量,赋值为2021年12月20日,判断 其是否闰年以决定是否输出,输出格式为YYYY-MM-DD。程序如下
#include<iostream>
#include <iomanip>
using namespace std;
//--------------------------------------------
struct Date
{
int year;
int month;
int day;
};
//--------------------------------------------
void print(Date);
bool isLeapYear(Date d);
void main()
{
Date d;
d.year = 2020;
d.month = 12;
d.day = 20;
if (isLeapYear(d))
print(d);
}
//--------------------------------------------
void print(Date s)
{
cout << setfill('0');
cout << setw(4) << s.year << '-' << setw(2) << s.month << '-' << setw(2) << s.day << '\n';
cout << setfill(' ');
}
//--------------------------------------------
bool isLeapYear(Date d)
{
return (d.year % 4 == 0 && d.year % 100 != 0) || (d.year % 400 == 0);
}
运行结果:
2、定义一个日期类
一样的题目,我们使用类来实现,程序如下:
#include<iostream>
#include <iomanip>
using namespace std;
//-----------------------------------------
class Date
{
int year;
int month;
int day;
public:
void set(int y, int m, int d);//赋值操作
bool isLeapYear();//判断闰年
void print();//输出日期
};
//------------------------------------------
void Date::set(int y, int m, int d)
{
year = y;
month = m;
day = d;
}
bool Date::isLeapYear()
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
//--------------------------------------------
void Date::print()
{
cout << setfill('0');
cout << setw(4) << year << '-' << setw(2) << month << '-' << setw(2) << day << '\n';
cout << setfill(' ');
}
//--------------------------------------------
void main()
{
Date d;
d.set(2020, 12, 20);
if (d.isLeapYear())
d.print();
}
运行结果:
(二)定义一个类
1、类定义
定义一个类需要使用关键字 class,然后指定类的名称,并类的主体是包含在一对花括号中,主体包含类的成员变量和成员函数。
定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
2、特别说明访问修饰符
(1)public--------公共的,外部可以访问;
(2)protected---保护的,外部不可以访问;
(3)private-------私有的,外部不能访问;
3、类与结构的区别
C++中,结构是用关键字struct声明的特殊的类,默认情况下其成员是public的。
类是用关键字class声明,默认情况下的成员是 private的。类除了有数据成员之外,还有对数据的操作,即成员函数。
(三)定义类的成员函数
1、什么是成员函数?
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。成员函数又叫方法(method).
2、在哪里定义成员函数?
成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符。
(1)把成员函数定义在类内部
定义一个Box类为例:
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
double getVolume(void)
{
return length * breadth * height;
}
};
(2)把成员函数定义在类外部
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
double getVolume(void);// 返回体积
};
double Box::getVolume(void)
{
return length * breadth * height;
}
3、将类定义分为两部分定义是通常做法
(1)先看这个把类定义为一部分的例子
class Date
{ int year, month, day;
public:
bool IsLealpYear()
{
return(year%4==0 && year%100!=0)||(year%400==0);
}
void Print()
{
cout<<month<<“/”<<day<<“/”<<year<<endl;
}
void Set(int m,int d,int y){month=m; day=d; year=y;}
};
(2)将上面的类定义分成两部分
一部分为类定义的头文件,另一部分为类的成员函数定义。将类定义和其成员函数定义分开,是目前开发程序的通常作法。(好处是更方便使用这个类)
// date.h 类定义
class Date
{
public:
void Set(int, int, int); //成员函数声明
int IsLeapYear();
void Print();
private:
int month, day, year;
}
//date.cpp //成员函数定义
#include <iostream.h>
#include “date.h”//这里要有头文件
void Date::Set(int m, int d, int y)
{
month=m;
day=d;
year=y;
}
int Date::IsLeapYear()
{
return(year%4==0&&year%100!=0)||(year%400==0);
}
void Date::Print()
{
cout<<month<<“/”<<day “/”<<year<<endl;
}
4、成员函数中,能够调用非成员函数。
例如下面的代码,在成员函数Set()中,调用了非成员函数Set()。
int month, day, year; //全局变量
void Set(int m, int d, int y) //非成员函数
{
::month=m; //给全局变量赋值
::day=d;
::year=y;
}
class Date
{
public:
void Set(int m, int d, int y) //成员函数
{
::Set(m,d,y) //调用非成员函数
}
private:
int month, day, year;
};
5、重载成员函数(Overloading Member Functions)
成员函数与普通函数一样,可以重载。 对重载的识别和使用规则也相同。
注:一个类的成员函数与另一个类的成员函数即使同名,也不能认为是重载。例如:
class Student
{public:
float grade(){//…}
float grade(float newGPA){//…}
//…
protected:
//…
};
class Slope
{ public:
float grade(){//…}
//…
protected:
//…
};
char grade(float value){//…}
void main()
{
Student s;
Slope t;
s.grade(3.2); //Student::grade(float)
float v=s.grade(); //Student::grade()
char c=grade(v); //::grade(float)
float m=t.grade(); //Slope::grade()
}
6、调用成员函数
调用成员函数的形式有:
(1)objectName.memberFunctionName(parameters);
(2)objectName->memberFunctionName(parameters);
(3)(*objectPointer).memberFunctionName(parameters);
举个例子:
#include<iostream>
#include <iomanip>
using namespace std;
class Date
{
int year;
int month;
int day;
public:
void set(int y, int m, int d);//赋值操作
bool isLeapYear();//判断闰年
void print();//输出日期
};
void Date::set(int y, int m, int d)
{
year=y;
month=m;
day=d;
}
bool Date::isLeapYear()
{
return (year%4 == 0 && year%100!=0) || (year%400==0);
}
void Date::print()
{
cout<<setfill('0');
cout<<setw(4)<<year<<'-'<<setw(2)<<month<<'-'<<setw(2)<<day<<'\n';
cout<<setfill(' ');
}
void main()
{
Date *dp=new Date;
dp->set(2021,12,6);//objectName->memberFunctionName(parameters)
if(dp->isLeapYear())
(*dp).print();//(*objectPointer).memberFunctionName(parameters)
}
7、在成员函数中访问成员
成员函数必须用对象来调用。但是,在成员函数内部,访问数据成员或成员函数无须如此。
为什么呢?(一个隐含的形参this指针)
说明:一个类对象所占据的内存空间由它的数据成员所占据的空间总和所决定。类的成员函数不占据对象的内存空间。
8、常成员函数(Const Member Functions)
成员函数的操作,如果只对对象进行读操作,则该成员 函数可以设计为常(const)成员函数。设计常成员函数 的好处是,让使用者一目了然地知道该成员函数不会改 变对象值,同时也方便调试。
常成员函数声明和定义的形式是在函数形参列表的右括 号后面加上const。看个例子:
bool isLeapYear() const; //声明
bool Date::isLeapYear() const //定义
{
………
}