C++面向对象具有三大特征:封装、继承、多态
首先是封装:
封装就是将属性和行为作为一个整体来表现事物,并将属性和行为加以权限控制。
就是程序段封装进一些东西使其变得完整。
类的表示方法为 class 类名;
在类中,具有三种访问权限,分别为public(公共)、protected(受保护的)和private(隐私)。下文详谈。
比如:设计一个圆类,来求圆的周长
求周长需要用到公式2*PI*半径,所以半径要作为圆的一个属性
举求圆周长例子来说明类的组成和封装方式:
class Circle
{
//访问权限为公共权限
public:
//属性
int m_r;//半径 - 成员变量
//行为
//获取圆的周长 - 成员函数
double calculateZC()
{
return 2 * PI * m_r;
}
};
int main()
{
//通过圆类创建一个具体的圆 - 对象
Circle c1;
//给对象的属性赋值
c1.m_r = 10;
cout << "圆的周长为:" << c1.calculateZC() << endl;
system("pause");
return 0;
}
再比如,定义一个 学生 类,包括学生的名字和ID号:
那么类中:
成员变量(属性)就应该为:名字、ID;
成员函数(行为)为:设置名字、设置ID、展示学生信息。
主函数中:
通过类创建一个类对象s1;(感觉跟c中创建结构体变量的方式相似);
通过成员函数设置和展示学生信息,注意调用成员函数要指明在s1对象内,所以函数名前要加“s1.”。
class Student
{
public://公共权限
//类中的属性和行为统一称为成员
//属性 成员属性 成员变量
string m_Name;
int m_Id;
//行为 成员函数 成员方法
void showStudent()
{
cout << "姓名:" << m_Name <<endl<< "学号:" << m_Id << endl;
}
void setName(string name)
{
m_Name = name;
}
void setId(int id)
{
m_Id = id;
}
};
int main()
{
//创建一个具体学生,实例化对象
Student s1;
//s1.m_Name = "张三";
s1.setName("张三");
//s1.m_Id = 1;
s1.setId(1);
//显示
s1.showStudent();
system("pause");
return 0;
下面就来说一下类的三种访问权限的具体作用,其实从名字就能看得出来,public、protected、private是逐渐私有的,可以说是保护力度逐渐增加。
所以就有:
public? ? ? ? 公共权限,其成员 类内可以访问,类外也可以访问 protected??保护权限,其成员 类内可以访问,类外不可以访问,子类可以访问父类的保护内容 private? ? ? ?私有权限,其成员 类内可以访问,类外不可以访问,子类不可以访问父类的私有内容
(子类、父类涉及到继承的问题,下面再说)
定义一个人类来感受一下类的访问权限:
在类中,定义名字为public,汽车为protected,密码为private。定义公共权限下的成员函数;并给三种属性赋值;
class Person
{
public:
//公共权限
string m_Name;//姓名
protected:
//保护权限
string m_Car;//汽车
private:
int m_Password;//密码
public:
void func1()
{
//类内都可以定义
m_Name = "zhangsan";
m_Car = "tuolaji";
m_Password = 12345;
}
};
那么在访问这三种不同访问权下的属性(成员变量)时,就会有以下现象:
只有public下的成员变量m_Name可以访问到,其他的在类外访问不到;
//实例化具体对象
Person p1;
p1.m_Name = "lisi";
p1.m_Car = "benz";//m_Car在类内是保护权限,在类外访问不到
p1.m_Password = 23456;//m_Password在类内是保护权限,在类外访问不到
上面提了一嘴类跟结构体相似,现在来填坑:
class和struct的主要区别时默认访问权限不同
struct 默认权限为公共 public class ?默认权限为私有 private 如果定义类时不指定访问权限,则为公共,而定义结构体时默认权限为私有。
所以c1.A访问不到,而c2.A可以访问到。
class C1
{
int A; //默认权限是私有
};
struct C2
{
int A; //默认权限是公共
};
int main()
{
C1 c1;
c1.A = 100;//私有,类外不可以访问 err
C2 c2;
c2.A = 100;//公共,可以访问
system("pause");
return 0;
}
好像public下的成员都能被访问,可以减少访问不到的错误,那么将访问权限设置为private的优势是什么呢?
:将所有成员属性设为私有,可以自己控制读写权限;对于写权限,我们可以检查数据的有效性;
比如定义一个Person类,将所有成员函数定义在public下,将所有成员变量定义在private下:
class Person
{
public:
void setname(string name)
{
m_name = name;
}
string getname()
{
return m_name;
}
void setage(int age)
{
if (age < 0 || age>150)
{
m_age = 0;
cout << "不可能!" << endl;
return;
}
m_age = age;
}
int getage()
{
return m_age;
}
void setlover(string lover)
{
m_lover = lover;
}
private://全设置为私有,类内可以访问,在上面public可以输出类外可用的结果,可以多种操作
string m_name;//可读可写
int m_age;//只读
string m_lover;//只写
};
这样虽然成员变量是私有的,但是在类内可以访问到,即类内的成员函数可以访问到,而成员函数又是定义在public下的,所以类外可以访问成员函数返回的内容;
具体的访问结果如下:
int main()
{
Person p;
p.name = "zhangsan";//私有,不可访问
p.setname("zhangsan");//成员函数public,可以访问
cout << "姓名:" << p.getname() << endl;
cout << "年龄:" << p.getage() << endl;
p.setlover("井");
cout << "情人:" << p.m_lover << endl;//err,私有的成员函数不可访问
p.setage(18);
cout << "年龄:" << p.getage() << endl;
system("pause");
return 0;
}
举两个例子:
案例一:求一个立方体的面积和体积并分别用全局函数和成员函数判断两个立方体是否相等。
拿到这个题先分析求其面积和体积,比较两个立方体是否相等需要用到什么属性和行为,属性为立方体三边的长度,行为为求面积、求体积、判断相等。
定义立方体类:
包括长宽高三个属性和设置长宽高的函数,然后在主函数中给长宽高赋值。
class Cube
{
//属性
private:
int m_L;
int m_W;
int m_H;
//行为
public:
//设置长
void setL(int l)
{
m_L = l;
}
//获取长
int getL()
{
return m_L;
}
//设置宽
void setW(int w)
{
m_W = w;
}
//获取宽
int getW()
{
return m_W;
}
//设置高
void setH(int h)
{
m_H = h;
}
//获取高
int getH()
{
return m_H;
}
//获取面积
int S()
{
return 2*m_L*m_W + 2*m_W*m_H + 2*m_L*m_H;
}
//获取体积
int V()
{
return m_L * m_W * m_H;
}
};
int main()
{
Cube c1;
c1.setL(10);
c1.setW(10);
c1.setH(10);
cout << "面积" << c1.S() << endl;
cout << "体积" << c1.V() << endl;
system("pause");
return 0;
}
以上两段程序中,在主函数中调c1类中的c1.set()函数,用来给L、W、H赋初值,在类中set函数将值设置为m_L、m_W、m_H的值,获取函数get()再得到赋值后的L、W、H。然后带入S()和V()函数中进行计算面积和体积;
那么怎么比较两个立方体是否相等(LWH都相等)呢?
首先要在主函数中再定义第二个立方体类c2:
Cube c2;
c2.setL(10);
c2.setW(10);
c2.setH(10);
然后在类中定义成员函数,属性为public:只需要传入一个新定义的立方体类来与已经存在的立方体类相比较。
bool issamebyclass(Cube &c)
{
if (m_L == c.getL() && m_W== c.getW() && m_H == c.getH())
{
return true;
}
return false;
可以看到函数的返回类型为bool(布尔型),只有true和false两个值。那么在主函数中进行用ret2接收函数返回结果并输出最终判断结果:
bool ret2 = c1.issamebyclass(c2);//成员 c1是已知的,与未知的c2进行对比
{
if (ret2)
{
cout << "相等2" << endl;
}
else
{
cout << "不等2" << endl;
}
}
那么利用局部函数呢,不在类内的实现jiushi常规的方法了,再定义一个函数就可以了:
所以在类外定义一个函数:跟成员函数相似的,只不过调用了两个参数,用来比较两个立方体。
bool issame(Cube& c1, Cube& c2)
{
if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH())
{
return true;
}
return false;
在主函数中接受:
bool ret1 = issame(c1, c2);//局部
{
if (ret1)
{
cout << "相等1" << endl;
}
else
{
cout << "不等1" << endl;
}
}
案例二:点和圆的关系
通过点(x2,y2)到圆心(x1,y1)的距离来判断:点在圆内,点在圆上,点在圆外
这次通过定义头函数(.h)的方式来实现:在头文件中定义类。
point.h
定义 点 类,定义设置坐标的成员函数
class Point
{
public:
//设置x
void setx(int x);
//获取x
int getx();
//设置y
void sety(int x);
//获取y
int gety();
private:
int m_X;
int m_Y;
};
circle.h
定义 圆?类,定义设置坐标和圆心的成员函数
class Circle
{
public:
//设置半径
void setr(int R);
//获取半径
int getr();
//设置圆心
void setcenter(Point center);
//获取圆心
Point getcenter();
private:
int m_R;
Point m_Center;
};
point.cpp
实现Point作用域下(Point::)的成员函数;
//设置x
void Point::setx(int x)//Point作用域下的成员函数
{
m_X = x;
}
//获取x
int Point::getx()
{
return m_X;
}
//设置y
void Point::sety(int y)
{
m_Y = y;
}
//获取y
int Point::gety()
{
return m_Y;
}
circle.cpp
实现Circle作用域下(Circle::)的成员函数;
//设置半径
void Circle::setr(int R)
{
m_R = R;
}
//获取半径
int Circle::getr()
{
return m_R;
}
//设置圆心
void Circle::setcenter(Point center)//setcenter是Circle中的成员函数
{
m_Center = center;
}
//获取圆心
Point Circle::getcenter()
{
return m_Center;
}
主函数文件:test.cpp
判断点和圆的位置关系;
//判断点和圆的关系
void isincircle(Circle & c, Point & p)
{
int distance =
(c.getcenter().getx() - p.getx()) * (c.getcenter().getx() - p.getx()) +
(c.getcenter().gety() - p.gety()) * (c.getcenter().gety() - p.gety());
int rdistance = c.getr()* c.getr();
if (distance == rdistance)
{
cout << "点在圆上" << endl;
}
else if (distance > rdistance)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在圆内" << endl;
}
}
?创建对象和成员函数传参:
int main()
{
//创建圆
Circle c;
c.setr(10);
Point center;
center.setx(10);
center.sety(0);
c.setcenter(center);
//创建点
Point p;
p.setx(10);
p.sety(9);
//判断关系
isincircle(c, p);
system("pause");
return 0;
}
|