/*
* 一、面向对象编程设计的基本特点
* (一)抽象
* 面向对象编程中的抽象,指的是针对具体问题进行概括,抽出一类对象的公共性质并加以描述的过程
* 对于一个问题的抽象包括两个方面1、数据抽象2、行为抽象
* 数据抽象:描述某类对象的属性或者状态
* 行为抽象:某类对象的共同行为或功能特征
* (二)封装
* 将抽象得到的数据和行为相结合,形成一个有机整体,也就是将数据与操作数据的函数代码进行有结合,形成类,其中的数据和函数都是类的成员
* (三)继承
* 类的继承机制允许程序员在保持原有的类的特性的基础上,进行更加具体,更加详细的说明
* (四)多态
* 多态性指的是一段程序可以处理队中类型的对象的能力,这种多态性可以通过强制多态、重载多态、类型参数化多态包含多态四种方式实现
* 二、类与对象
* 在面向对象编程中,程序模块是由类构成的,类是对逻辑上相关的函数与数据的封装,它是对问题的抽象描述
* (一)类的定义
* class clock//class 类名称
* {
* public://外部接口
* void settime(int h,int m,int s);
* void showtime();
* private://私有成员
* int hour;
* int minute;
* int second;
* protected://保护型成员
*
* }
* (二)类成员的访问控制
* 访问控制属性一共有三种:public(公有的)private(私有的)protected(保护的)
* public公有类型成员定义了类的外部接口,类外只能访问类的公有成员
* private后面声明的就是私有成员,只能被本类的成员函数访问,来自外部的任何访问都是非法的
* protected后面声明的是保护类成员,和私有成员性质相似,差别在于继承过程中对于产生新类影响不同
* 设计一个类,一定要有外部接口,不同属性的成员,可以按照不同的顺序出现,但是一个成员只能有一种属性
* (三)对象
* 1、声明对象
* 类的特定实体就是对象,比如定义一个clock类,用clock myclock; 就是声明了一个对象
* 声明对象: 类名 对象名;
* 对象所占有的空间只用来存储数据成员,函数成员不在每一个对象中储存副本,每个函数的代码只在内存中占用一部分空间
* 2、访问对象成员
* 定义类和对象之后,就可以访问对象的成员,用符号“.”来访问,比如 myclock.settime(参数列表)
* 访问对象成员: 对象名.函数成员名(参数列表)
* 在类的外部只能访问到公有的成员成员,在类的成员函数中,可以访问到类的全部成员
* (四)成员函数
* 类的成员函数描述的是类的行为
* 1、成员函数的实现
* 函数的原型声明要写在类体中,原型要说明函数的参数列表和返回值类型,函数的具体实现写在类的而定义之外
* 实现函数成员时要指明类的名称
* 返回值类型 类名:函数成员名(参数列表)
* { 函数体 }
* 2、成员函数调用中的目的对象
* myclock.settime(形参)其中myclock就是本次调用中的目的对象
* 3、带默认形参的成员函数
* 类的成员函数的默认值一定要写在类的定义中,不能写在类定义之外的函数中实现,其调用规则和普通还能输相同
* 4、内联函数
* 内联函数的函数体在编译时,被插入到每一个调用它的地方
* 以空间换时间的方法,对于编译器而言只是一个建议,编译器会自动优化
* 不建议声明和定义分开,会没有函数地址就找不到链接
* 扩展:宏定义分为两种:带参数的和不带参数的(预处理)
* 1、不带参数的宏定义,又称为宏替换
#define 标识符(宏名) 字符串//将宏名替换成字符串
在做任何事件之前及逆行替换
例如:#define PI 3.141567
把程序中出现的所有的PI都替换成3、141567
2、带参数的宏,除了一般的字符串替换,还要做参数替换
#define 宏名(参数表)字符串
例如:#definr S(a,b)a*b
area=S(3,2)
第一步area=a*b,第二步 area=3*2;
* 内联函数和宏的区别:
* 1、内联函数在编译时展开,宏在编译前
* 2、内联函数直接镶嵌到函数中,宏只做简单的替换
* 3、内联函数又类型检测、语法判断等功能,宏只是替换
* 三、构造函数和析构函数
* 在定义对象的时候进行数据成员的设置,称为对象的初始化,在特定对象使用结束后,还经常需要进行一些处理工作,分别由两个函数进行完成就是构造函数和析构函数
* (一)构造函数
* 在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态
* 特殊性质:
* 1、构造函数的函数名与类名相同,并且没有返回值
* 2、构造函数通常被声明为共有函数
* 3、构造函数在对象被创建时自动调用
* 调用时,无需提供参数的构造函数称为默认构造函数,如果类中没有写构造函数,编译前会自动生成一个默认的构造函数,参数列表和函数体都为空
* 如果类中声明了构造函数则编译器不会在生成隐含的构造函数
* (二)复制构造函数
* 生成对象的副本有两种途径,一种是建立一个新对象,将已有的数据成员取出来一一复制新的成员,第二种,复制构造函数
* 复制构造函数,具有构造函数的所有特性,其形参是本类对象的引用,其作用是用一个已经存在的对象(由复制构造函数的参数指引)去初始化一个同类的新对象
* 如果程序员没有定义复制构造函数,系统就会在必要时生成一个隐含的复制构造函数,这个隐含复制构造函数的功能是把初始值对象的每个数据成员都复制到新建的对象中
* 声明和实现复制构造函数的一般方法
* class 类名
*
{
public:
类名(形参表);//构造函数
类名(类名&对象名)//复制构造函数
};
类名::类名(类名&对象名);//复制构造函数的实现
{
函数体
}
* 复制构造函数的三种调用情况
* 1、用类的一个对象去初始化另外一个类时
* 2、函数的形参是类的对象,调用函数时进行形参实参相结合
* 3、函数的返回值是类的对象,函数执行完成返回调用者时
* (三)析构函数
* 用来完成对象被删除前的一些清理工作,析构函数时在对象的生存期季节昂结束的时候被自动调用的
* ~类名 析构函数
* 没有返回值,不接受任何参数,但可以是虚函数
* 如果不显示说明,系统会自动生成一个没有函数体的析构函数(未必不做任何事)
* (四)程序实例
* 四、类的组合
* (一)组合
* 类的组合描述的是一个类内嵌其他类的对象作为成员的情况,他们之间的关系是一种包含和被包含的关系
* 当创建类的对象时,如果这个类具有内嵌对象成员,那么各个内嵌对象将首先被自动创建
* 在创建对象时,既要对本类的基本类型数据成员进行初始化,又要对内嵌对象成员进行初始化
* 组合类构造函数定义的一般形式为:
* 类名::类名(形参列表):内嵌对象1(形参表),内嵌对象2(形参表)……
* { 类的初始化 }
* 创建一个组合类的对象时,不仅它自身的构造函数的函数体要执行,并且,还将调用其内嵌对象的构造函数
* 调用构造函数的顺序:
* 1、调用内嵌对象的构造函数(按照在组合类中出现的顺序,与初始化列表中出现的顺序无关)
* 2、执行本类构造函数的函数体
* 调用析构函数的顺序与构造函数刚好相反
* 析构函数的函数体被执行完毕后,内嵌对象的析构函数被执行,调用顺序与在组合类中的定义顺序刚好相反
* 如果要为组合类编写复制构造函数,则需要为内嵌成员的复制构造函数传递参数
* 例:c类中含有B类的成员b作为成员,c类的复制构造函数如下:
c::c(c&c1):b(c1.b){};
* (二)向前引用说明
* 引用未定义的类之前,将类的名字告诉翻译器,但是只是一个类名,不能给出该类的完整定义
* 五、UML图形标识
* (一)简介
* 统一建模语言UMl
* (二)UMLl类图
* 上中下三段,最上边是类的名称,中间是数据成员(属性),最下边是函数成员(行为),以及各个成员的访问控制属性
* 六、结构体和联合体
* (一)结构体
* 一种特殊形态的类,也可以有自己的数据成员和函数成员,可以有自己的构造函数和析构函数,可以控制访问权限,可以继承,支持包含多态等
* 结构体和类唯一的区别在于,结构体和类具有不同的默认访问控制属性
* 在类中,对于未知的访问控制属性成员,默认为私有的,而结构体默认为公有的
* 在结构体中,如果公有成员写在最前面,则public可以省略不写
* struct 结构体名称
{
公有成员
proteced:
保护成员
private:
私有成员
}
* (二)联合体
* 联合体的全部数据成员共享同一组内存单元
* 默认访问属性为公有的
* union 联合体名称{
* 公有成员
provate:
私有成员
pritected;
保护成员 };
* 七、例
* 八、深度探讨
* (一)位域
* 允许将类中的多个数据成员打包,从而使不同的成员可以共享相同的直接的机制
* 在类定义中,位域的定义方法:
* 数据类型说明符 成员名 :位数;
* 可以通过:后的位数来指定一个位域所占用的二进制位数
* 注意事项:
* 1、不同编译器与不同的处理方式,,包含位域的类所占用的空间大小也不同
* 2、bool、char、int 、enum才可以被定义成位域
* 3、节省内存空间,但是可能会增加运行时间
* 结构体和类都允许定义位域,联合体本身就共用相同的存储单元,没必要也不允许定义位域
* 一个字节能存储8个二进制位
* (二)用构造函数定义类型转换
* 类型转换构造函数是一种构造函数,只有一个参数,不属于复制构造函数
* 作用:实现类型的自动转换
* 需要时,编译系统会自动调用转换的构造函数,建立一个无名的临时对象(临时变量)
* 什么时候被调用:1、发生在初始化语句
* 2、发生在赋值语句
* (三)对象作为函数参数和返回值
* 传递数据需要将实参值复制到运行栈的区域,,基本数据类型只需要做一般的内存操作即可,对象作为形参要调用复制构造函数
* 有时候编译器会进行优化,使复制构造函数不需要被调用,
* 复制构造函数一定值完成对象复制的任务,不需要有其他能产生副作用的操作,否则运行结果会因为编译器的优化程度而有所改变
*
*
#include<iostream>
#define PI 3.14
using namespace std;
*/
//封装一个clock类
class clock1//class关键字
{
public://关键字,指定访问权限
clock1(){};//编译系统生成的默认的构造函数
void settime(int h=1, int m=1, int s=1);//函数的原型声明写在类中,
void showtime()
{
cout << hour << ":" << minute << ":" << second << endl;
};
private://关键字,指定访问权限
int hour;
int minute;
int second;
};
//函数的具体实现在函数的外部
//settime函数
void clock1::settime(int h,int m,int s)//指明类的名称是clock1;
{
hour = h;
minute = m;
second = s;
}
//showtime函数
//inline void clock1::showtime()//内联函数,牺牲空间来减少时间
//{
// cout << hour << ":" << minute << ":" << second << endl;
//}
class clock2
{
public:
clock2(int h, int m=1, int s=1)
{
hour = h;
minute = m;
second = s;
}
clock2()
{
hour = 0;
minute =0;
second = 0;
}
void showtime()
{
cout << hour << ":" << minute << ":" << second << endl;
}
private:
int hour;
int minute;
int second;
};
//复制构造函数
class point
{
public:
point(int xx = 0, int yy = 0)//构造函数
{
x = xx;
y = yy;
}
point(point& p);
void showpoint()
{
cout << x << y << endl;
}
private:
int x;
int y;
};
point::point(point& p)
{
x = p.x;
y = p.y;
}
void f(point p) {}//函数的形参是类的对象,复制构造函数被调用
point g()
{
point a(2, 2);
return a;
}
//泳池半径由键盘输入,泳池外过道3m,20元每平方米,栅栏35元每米,求栅栏和过道的价格
class yongchi
{
public:
yongchi(float r);
float zhouchang();
float mianji();
private:
float banjing;
};
yongchi::yongchi(float x)
{
banjing = x;
}
float yongchi::zhouchang()
{
float l = 2 * (banjing+3) * PI;
return l;
}
float yongchi::mianji()
{
float a=PI * banjing * banjing;
float b = PI * (banjing + 3) * (banjing + 3);
return (b-a)*35;
}
//类的组合
class line
{
public:
line(point x, point y)
{
p1 = x;
p2 = y;
}
line(line& l);
private:
point p1, p2;
double len;
};
//组合类的构造函数
line::line(point x, point y) :p1(x), p2(y)
{
}
//组合类的复制构造函数
line::line(line& l) : p1(l.p1),p2(l. p2)
{
}
//主函数
int main()
{
float e,h,i;
cin >> e;
yongchi d(e);
h=d.zhouchang();
i = d.mianji();
cout << "栅栏造价是"<<h * 3 << endl;
cout <<"过道造价是"<< i << endl;
point p(1,2);
point b;
point a(p);
f(b);
point c;
c = g();
c.showpoint();
p.showpoint();
b.showpoint();
a.showpoint();
clock1 myclock;
myclock.settime();
myclock.showtime();
myclock.settime(8, 8, 8);
myclock.showtime();
clock2 myclock2;//调用无参构造函数
clock2 myclock3(1);//调用有参构造函数 注意防止有参和无参函数调用不明确
myclock2.showtime();
myclock3.showtime();
}