类和对象
c++面向对象的三大特性:封装,继承,多态
c++认为万事万物都是对象,对象上有其属性和行为(一定有)
例如:
人为对象,属性:姓名,年龄,身高,体重。行为:走,跑,跳。
车为对象,属性:轮胎,方向盘,车灯。行为:载人,放音乐,放空调
具有相同性质的对象,我可将其抽象为类,人属于人类,车属于车类
4.1封装
4.1.1封装的意义
封装是c++面向对象的三大特性之一
封装的意义:
-
将属性和行为作为一个整体,表现事物
-
将属性和行为加以权限控制
封装的意义一:
//设计一个圆类,求圆的周长 //求圆的周长:2*PI*半径 语法:class 类名{ 访问权限:属性 / 行为 }; #include<iostream> using namespace std; //圆周率 const double PI = 3.14; //设计一个圆类,求圆的周长; //圆求周长的公式: 2*PI*半径 class circle { public://访问权限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"); } #include<iostream> #include<string> using namespace std; //设计一个学生类 class student { public: //属性 string m_name;//学生名 int m_ID;//学号 //行为 显示学生的姓名和学号 void showstudent() { cout << "姓名: " << m_name << "学号: " << m_ID << endl; } }; int main() { //创建一个具体学生 student s1; s1.m_name = "张三"; s1.m_ID = 1; s1.showstudent(); student s2; s2.m_name = "李四"; system("pause"); return 0; }
可以通过行为对类中的属性赋值
#include<iostream> using namespace std; //设计一个学生类 class student { public: //类中的属性和行为统一称为成员; // 属性构成: 成员属性 成员变量 // 行为 成员函数/成员方法 //属性 string m_name;//学生名 int m_ID;//学号 public://重复的public可写可不写 //行为 显示学生的姓名和学号 void showstudent() { cout << "姓名: " << m_name << "学号: " << m_ID << endl; } //调用类里的函数对类里的属性进行赋值 //给姓名赋值 void setName(string name) { m_name = name;//m_name相当于类中的全局变量可以被类中的函数改变值 } }; int main() { //创建一个具体学生 student s1; //s1.m_name = "张三"; //s1.m_ID = 1; s1.setName("张三");//调用类中的成员函数来给成员属性赋值; s1.showstudent();//会直接输出这个是学生的学号和姓名 student s2; s2.m_name = "李四"; system("pause"); return 0; }
封装意义二:
struct默认权限为公共权限(public),class默认为私有权限(private)
类在设计时可以把属性和行为放在不同的权限下,加以控制
访问权限有三种:
-
public 公共权限
-
protected 保护权限
-
private 私有权限
//公共权限 public:成员:类内可以访问,类外也可以访问
//保护权限 protected: 成员:类内可以访问 ,类外不可以访问 区别(儿子可以访问父亲中的保护内容)
//私有权限 private : 成员:类内可以访问 ,类外不可以访问 区别(儿子不可以访问父亲中的保护内容)
class person
{
public://公共权限
string m_name;
protected://保护权限
string m_car;
private://私有权限
int m_password;//银行卡密码
public:
void func()
{
m_name = "zhang";
m_car = "拖拉机";
m_password = 123456;
}
};
int main(){
person p1;
p1.m_name = "li";
p1.m_car = "bengchi";//此处会报错
p1.m_password = 123;//也会报错私有权限内容无法访问
}
4.1.2struct和class的区别
c++中class和struct唯一的区别在于默认的访问权限不同
struct默认权限为公共权限(public),class默认为私有权限(private)
class c1{ int m_a;//不写权限则就是默认权限,是private }; struct c2{ int m_a;//默认权限是公共 }; int main(){ c1 s1; s1.m_a = 100;//会报错 c2 s2; c2.m_a = 100;//不会报错可以访问可以输出; }
4.1.3将成员属性设为私有
优点1. 将所有成员属性设为私有,可以自己控制和读写权限
优点2. 对于写权限,我们可以检测数据的有效性;
#include<iostream> #include<string> using namespace std; //设计人类 class person { public://读写接口 //写姓名 void setname(string name){ m_name = name; } //读姓名 string getname(){ return m_name; } //检测数据有效性 int getage(){ return m_age; } //设置年龄 void setage(int age){ if(age<0||age>150){ m_age = 0; cout<<"不可能的年龄"<<endl; return; } m_age = age; } private://已经被设为私有无法别外部访问但可以被内部函数访问,因此可以采用public接口来对属性进行访问 string m_name;//姓名 可读可写 int m_age;//年龄 可读不可泄 string m_lover//只写 }; int main(){ person s1; s1.setname("张三");//通过public接口改变私有权限内的数据 cout<<"姓名为:"<<s1.getname()<<endl; s1.setage(1000); cout<<s1.getage()<<endl;//此时输出 不可能的年龄 //0, 先输出不可能的年龄后输出0. }
set写 get读
这里函数内的 m_name m_age等等变量,作用域在这个class内(因为是private权限),生命周期为main函数里 使用这个class定义一个对象开始,到main函数结束,所以可以在类中的函数内直接使用
练习案例:设计立方体类
设计立方体类:
求出立方体的面积和体积
分别用全局函数和成员函数判断两个立方体是否相等
#include<iostream> #include<string> using namespace std; // //设计一个立方体类 class cube { public: //设置长宽高 void setl(int l) { m_l = l; } void setw(int w) { m_w = w; } void seth(int h) { m_h = h; } //获取长宽高 int getw() { return m_w; } int getl() { return m_l; } int geth() { return m_h; } //获取立方体面积 int calculates() { return 2 * (m_l * m_w + m_l * m_h + m_h * m_w); } //获取立方体体积 int calculatev() { return m_l * m_w * m_h; } //用类内函数对两个立方体进行判断是否相等 bool issamebycube(cube& c) { if (m_h == c.geth() && m_l== c.getl() && m_w== c.getw())//m_h,m_w,m_l都是调用这个该函数的对象的,而c是被放入函数中的 //因为用了c1的成员函数,c1的值可以直接在自己的类里边调用,所以只传c2就可以了 return 1; return 0; } private: int m_l; int m_h; int m_w; }; //里用全局函数判断两个立方体是否相等 bool issamebycube(cube& c1, cube & c2)//引用直接对原始数据操作 { if (c1.geth() == c2.geth() && c1.getl() == c1.getl() && c1.getw() == c2.getw()) return 1; return 0; } int main() { cube c1; c1.setl(20); c1.seth(100); c1.setw(79); cout << "c1的体积" << c1.calculatev() << endl; cout << "c1的面积" << c1.calculates() << endl; cube c2; c2.setl(8); c2.setw(90); c2.seth(77); cout << "c2的体积" << c2.calculatev() << endl; cout << "c2的面积" << c2.calculates() << endl; cout << "两个立方体是否相等:" << ((issamebycube(c1, c2) == 1) ? "相等" : "不相等") << endl; cout << "两个立方体是否相等;" << (c1.issamebycube(c2) == 1 ? "相等" : "不相等") << endl; //因为用了c1的成员函数,c1的值可以直接在自己的类 里边调用,所以只传c2就可以了 system("pause"); return 0; }
类中有类
在类中可以有另一个类作为其成员
#include<iostream> #include<string> using namespace std; //设计一个点类 class point { public: void setx(int x) { m_x = x; } void sety(int y) { m_y = y; } int getx() { return m_x; } int gety() { return m_y; } private: int m_x; int m_y; }; //设计一个圆类 class circle { public: void setr(int r) { m_r = r; } int getr() { return m_r; } void setcenter(point center) { m_center = center; } point getcenter() { return m_center; } private: int m_r; point m_center;//圆心在一个类中可以让另一个类成为本类中的成员 }; //判断点和圆的关系 void isincircle(circle& c, point& p) { int distence = (c.getcenter().getx() - p.getx())* (c.getcenter().getx() - p.getx()) + (c.getcenter().gety() - p.gety()) * (c.getcenter().gety() - p.gety()); int cdistence = c.getr() * c.getr();//无论有没有参数传入都要带(). if (distence == cdistence) cout << "点在圆上" << endl; else if (distence > cdistence) cout << "点在圆外" << endl; else cout << "点在圆内" << endl; } int main() { circle c; c.setr(10); point p; point p1; p.setx(8);//要先设置圆心位置 p.sety(9); c.setcenter(p);//设置圆心 p1.setx(7); p1.sety(6); isincircle(c, p1);//传入的是圆而不是圆心 system("pause"); return 0; }
在头文件中写类的声明;
在源文件中写类的实现;要加成员函数的作用域例如circle:: , point:: 是在函数名前面加