【类和对象的使用的知识点——案例1设计一个类的立方体,可以计算立方体的面积和体积和案例2创建点和圆的类,判断圆和点的关系】
创始人
2025-06-01 00:42:58
0

文章目录

  • 类和对象的使用的知识点
    • 封装
      • 封装的意义
      • struct和class区别
      • 成员属性设置为私有
    • 对象的初始化和清理
      • 构造函数和析构函数
      • 构造函数的分类及调用
      • 拷贝构造函数调用时机
      • 构造函数调用规则
      • 深拷贝和浅拷贝
      • 初始化列表

类和对象的使用的知识点

C++面向对象的三大特性为:封装,继承,多态
C++认为万事万物都皆为对象,对象上有其属性和行为
Eg:人可以作为一个对象,属性有姓名,年龄,身高,体重…行为有走,跑,跳…
车也可以作为对象,属性有轮胎,方向盘,车灯…行为有载人,放音乐,放空调
具有相同性质的对象,我们可以抽象为类,人属于人类,车属于车类

封装

封装的意义

封装是C++面向对象三大特性之一
封装的意义:1. 将属性和行为作为一个整体,表现生活中的事物

将属性和行为加以权限控制

封装的意义一:在设计类的时候,属性和行为写在一起,表示事物,
语法:class 类名{ 访问权限 :属性 / 行为 };

#include 
using namespace std;
const double PI = 3.14;class Circle {//访问权限,这里先暂时不解释
public://属性int m_r;//行为double calculate2C() {return 2 * PI * m_r;}
};int main()
{//通过一个圆类创建具体的圆(类)//实例化,通过一个类来创建一个对象的过程Circle c1;//给对象进行赋值c1.m_r = 10;//圆的周长公式 C = 2 * PI * rcout << "圆的周长为:" << c1.calculate2C() << endl;system("pause");return 0;
}

//设计一个学生类,属性有姓名学号,可以给姓名学号赋值,可以显示学生的姓名和学号

#include 
using namespace std;
class Student {//访问权限
public://属性(成员属性或成员变量)string m_Name;int m_Id;//行为(成员函数或者成员方法)void setName(string name) {m_Name = name;}void setID(int id) {m_Id = id;}void showStudent() {cout << "学生姓名:" << m_Name << "\n学生学号: " << m_Id << endl;}};
int main()
{Student s1;s1.setName("xiaochen");s1.setID(118);s1.showStudent();
}

封装意义二:类在进行设计时,可以把属性和行为放在不同的权限下,加以控制
访问权限有三种:

1.public 公共权限:类内可以访问,类外可以访问

2.protected 保护权限:类内可以访问,类外不可以访问,儿子可以访问父亲中的保护内容

3.private 私有权限:类内可以访问,类外不可以访问,儿子不可以访问儿子的私有内容

#include 
using namespace std;
class Person {
public:string m_Name;
protected:string car;
private:string password;
public:void func(){m_Name = "陈赢";car = "拖拉机";password = "123456";}
};
int main()
{Person p1;p1.m_Name = "小陈";cout << p1.m_Name << endl;//p1.car="benchi";//p1.password="qwert";这两个属性都是访问不到的,因为这两个属性的访问权限收限制
}

struct和class区别

在C++中struct和class唯一的区别就是在于默认访问的权限不同
struct默认的访问权限为公共的,class默认访问的权限是私有的

成员属性设置为私有

优点1:将所有成员属性设置为私有,可以自己控制读写权限
优点2:对于写权限,我们可以检测数据的有效性
成员的访问有权限的控制,可以通过将属性进行私有化,在利用成员函数公共化,类内元素可以访问的条件,就可以达到这样的效果

#include 
#include 
using namespace std;
class Person
{
public://可读成员方法string getName() {return m_Name;}//可写成员方法void setName(string name) {m_Name = name;}//只读函数int getAge() {return m_Age;}void setAge(int age) {if (age < 0 || age > 150) {cout << "你输入的年龄有问题,请重新输入" << endl;m_Age = 0;return;}m_Age = age;}//只写函数void setLover(string lover) {m_Lover = lover;}private:string m_Name;//可读可写int m_Age;//只读string m_Lover;//只写};
int main()
{Person p1;p1.setName("小陈");p1.setLover("小刘");p1.setAge(200);cout << "年龄:" << p1.getAge() << endl;cout << "姓名:" << p1.getName() << endl;system("pause");return 0;
}

封装案例1:
问题:设计一个类的立方体,可以计算立方体的面积和体积,并且分别用全局函数和成员函数进行判断两个立方体是否相同

#include 
using namespace std;
class Cube {//成员的函数(方法)
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 calculcateS() {return m_L * m_W * 2 + m_L * m_H * 2 + m_W * m_H * 2;}//计算立方体的体积int calculcateV() {return m_L * m_W * m_H;}//成员函数判断bool isSameByClass(Cube& c) {if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH()) {return true;}elsereturn false;}//成员属性:各个立方体的属性
private:int m_L;int m_W;int m_H;
};//利用全局函数来判断两个函数是否相等
bool isSame(Cube& c1, Cube& c2) {if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH()) {return true;}return false;
}
int main()
{//创建第一个立方体Cube c1;c1.setL(10);c1.setW(10);c1.setH(10);cout << "第一个立方体的面积为:" << c1.calculcateS() << endl;cout << "第一个立方体的体积为:" << c1.calculcateV() << endl;//创建第二个立方体Cube c2;c2.setL(10);c2.setW(10);c2.setH(10);cout << "第二个立方体的面积为:" << c2.calculcateS() << endl;cout << "第二个立方体的体积为:" << c2.calculcateV() << endl;//调用全局函数判断bool ret = isSame(c1, c2);if (ret) {cout << "全局函数:两个立方体相等" << endl;}else {cout << "全局函数:两个立方体的不相等" << endl;}//调用成员函数判断int ret_class = c1.isSameByClass(c2);if (ret_class) {cout << "成员函数调用:两个立方体相等" << endl;}else {cout << "成员函数调用:两个立方体不相等" << endl;}system("pause");return 0;}

总结:在进行全局函数和成员函数判断的时候,成员函数可以只传入一个参数,本身又调用自己的成员函数
注意代码的规范,每一步细化

封装案例2:
总结:在类中可以让另一个类作为本来中的成员
在这个案例中,存在每个类进行分类并且用头文件和cpp 文件进行分开操作,在后续的修改更加方便

//创建点和圆的类,判断圆和点的关系#include 
#include 
using namespace std;
class Point {//成员的函数
public://设置x的坐标void setX(int x) {m_X = x;}//获取x的坐标int getX() {return m_X;}//设置y的坐标void setY(int y) {m_Y = y;}//获取y的坐标int getY() {return m_Y;}//成员的属性	
private:int m_X;int m_Y;
};class Circle {//成员的函数,设置获取半径的大小,计算两点之间的距离,设置P点
public://设置半径的大小void setR(int r) {m_R = r;}//获取半径的大小int getR() {return m_R;}//设置圆心的大小void setCenter(Point m) {center = m;}//获取圆心的大小Point getCenter() {return center;}//成员的属性:圆的半径和圆心,计算两者之间的距离
private:int m_R;Point center;int d;
};void calculateDistance(Circle& O, Point& p) {//计算两点之间的距离int distance =(O.getCenter().getX() - p.getX()) * (O.getCenter().getX() - p.getX()) +(O.getCenter().getY() - p.getY()) * (O.getCenter().getY() - p.getY());//计算半径的平方int rdistance = O.getR() * O.getR();if (distance == rdistance) {cout << "点在圆上" << endl;}else if (distance > rdistance){cout << "点在圆外" << endl;}else {cout << "点在圆内" << endl;}
}int main()
{//创建一个P点Point p1;p1.setX(10);p1.setY(10);cout << "P点的x坐标为:" << p1.getX() << endl;cout << "P点的y坐标为:" << p1.getY() << endl;//创建圆心Point m;m.setX(10);m.setY(0);cout << "圆心X坐标为:" << m.getX() << endl;cout << "圆心Y坐标为:" << m.getY() << endl;//创建一个圆Circle O1;O1.setR(10);O1.setCenter(m);cout << "圆的半径为:" << O1.getR() << endl;calculateDistance(O1, p1);system("pause");return 0;
}

对象的初始化和清理

构造函数和析构函数

(1)、构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用

(2)、析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作

构造函数:类名(){}

1.构造函数,没有返回值也不写void

2.函数名称与类名相同

3.构造函数可以有参数,因此可以发生重载

4.程序在调用对象的时候会自动调用构造,无须手动调用,且只会调用一次

析构函数:~类名(){}

1.析构函数,没有返回值也不写void

2.函数名称与类名相同,在名称前加上~

3.构造函数不可以有参数,因此不可以发生重载

4.程序在对象的时候会自动调用构造,无须手动调用,且只会调用一次

构造和析构都是必须有的实现,如果我们自己不提供,编译器会提供一个空实现的构造和析构

#include 
using namespace std;
class Person {
public:Person(){cout << "Person的构造函数" << endl;}~Person(){cout << "Person的析构函数" << endl;}
};//构造函数和析构函数都是自动会调用的,在进行销毁的时候,主要看数据存放的位置
//例如这个函数存放在栈区,在调用完这个函数的时候就会自动进行销毁,所以进能够看到调用析构函数void test01()
{Person p;
}int main()
{Person p1;//test01();system("pause");return 0;
}

构造函数的分类及调用

两种分类的方式:
按参数分:有参构造和无参构造
按类型分:普通构造和拷贝构造
三种调用的方式:括号法,显示法,隐式转换法

#include 
using namespace std;
class Person {
public://构造函数Person() {cout << "Person的无参构造函数" << endl;}Person(int a){age = a;cout << "Person的有参构造函数" << endl;}//拷贝构造函数Person(const Person& p) {age = p.age;cout << "Person的拷贝构造函数" << endl;}//析构函数~Person() {cout << "Person的析构函数调用" << endl;}private:int age;
};void test01() {//括号法Person p1;//构造函数无参调用Person p2(10);//构造函数有参调用Person p3(p2);//拷贝构造函数调用//注意事项1:调用默认构造函数的时候,不能加 (),因为加上编译器就会认为这是一个函数声明//显示法Person p4;Person p5 = Person(10);//有参构造Person p6 = Person(p5);//拷贝构造//隐式转换法//Person(10);这个是属于匿名对象,特点:当前执行结束后,系统就会立即回收掉匿名对象//注意事项2:不要利用拷贝构造函数来初始化匿名对象,编译器会认为这个是一个对象的声明//隐式转换法Person p7 = 10;//相当于写了Person p4=Person(10);有参构造Person p8 = p7;//拷贝构造}int main()
{test01();system("pause");return 0;
}

拷贝构造函数调用时机

C++中拷贝构造函数调用的时机通常由三种情况:

  1. 使用一个已经创建完毕的对象来初始化一个新对象

  2. 值传递的方式给函数参数传值

  3. 以值的方式返回局部对象

#include 
using namespace std;
class Person {
public://构造函数Person() {cout << "Person的无参构造函数" << endl;}Person(int a){age = a;cout << "Person的有参构造函数" << endl;}//拷贝构造函数Person(const Person& p) {age = p.age;cout << "Person的拷贝构造函数" << endl;}//析构函数~Person() {cout << "Person的析构函数调用" << endl;}public:int age;
};//使用一个已经创建完毕的对象来初始化一个新对象void test01() {Person p1(20);Person p2(p1);cout << "p2的年龄: " << p2.age << endl;
}// 值传递的方式给函数参数传值
//值传递就相当于在栈区开辟一块新的空间,拷贝过去所有的值,但是本身的值是不会改变的,他们所指的不是同一个地址
void doWork(Person p) {}void test02() {Person p;doWork(p);
}//以值的方式返回局部对象Person doWork2() {Person p1;return p1;
}void test03() {Person p = doWork2();
}int main()
{//test01();//test02();test03();system("pause");return 0;
}

构造函数调用规则

默认情况下:C++的编译器至少给一个类添加3个函数

  1. 默认构造函数(无参,函数体为空)

  2. 默认析构函数(无参,函数体为空)

  3. 默认拷贝构造函数,对属性进行值拷贝

构造函数的调用规则如下:

  1. 如果用户定义有参构造函数,C++不在提供默认无参构造函数,但是会提供默认拷贝函数

  2. 如果用户定义拷贝构造函数,C++不会提供默认其他构造函数

深拷贝和浅拷贝

深浅拷贝是一个常见的坑
浅拷贝:简单赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作

#include 
using namespace std;
class Person {
public:Person() {cout << "Person的无参构造函数" << endl;}Person(int age, int height) {m_Age = age;m_Height = new int(height);cout << "Person的有参构造函数" << endl;}Person(const Person& p) {cout << "Person的拷贝构造函数" << endl;m_Age = p.m_Age;m_Height = new int(*p.m_Height);}~Person() {if (m_Height != NULL){delete m_Height;m_Height = NULL;}cout << "Person的析构函数" << endl;}int m_Age;int* m_Height;
};void test01()
{Person p1(18, 160);cout << "p1的年龄:" << p1.m_Age << "p1的身高:" << endl;Person p2(p1);cout << "p2的年龄:" << p2.m_Age << "p2的身高:" << endl;
}
int main()
{test01();system("pause");return 0;
}

总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题。
因为浅拷贝仅仅只是简单的赋值,但是当数据是一个地址,并且拷贝的时候肯定是指向同一个地址,但是在进行删除操作的时候,就有一个找不到,因为已经被删除了,他们指的是同一片空间,但是在自己写的拷贝函数就是两个相同的存放地址的元素,虽然值相等,但是他们所指的空间是不同的

初始化列表

作用:C++提供初始化列表语法,用来初始化属性
语法:构造函数():属性1(值1),属性2(值2)…{}

#include 
using namespace std;
class Person {
public:Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}void printPerson() {cout << "mA=" << m_A << endl;cout << "mB=" << m_B << endl;cout << "mC=" << m_C << endl;}private:int m_A;int m_B;int m_C;};
int main()
{Person p(30, 20, 10);p.printPerson();system("pause");return 0;
}

7.类对象作为类成员
C++类中的成员可以是另一个类的对象,我们就称该对象为成员对象


总结:通过实验,我深刻领会类与对象的区别,类实现数据隐藏与封装的原理,并对C++编程有了更进一步的理解。掌握了声明类的方法,类和类的成员概念以及定义对象的方法,也掌握了成员函数的实现与调用方法,掌握引检查和调试基于对象的程序的方法。在学习类与对象的时候,了解写程序又两种方法,一个是面向过程,一个是面向对象,其中面向过程就是直接通过主函数或者借用其他函数,在主函数中直接写算法程序,但是面向对象的程序,就是要先创建对象,例如老师让我们定义一个学生,在处理学生的信息程序上面,就需要考虑学生的信息,学号,班级,成绩等等,然后在定义出学生这一类后,在进行对类操作的函数,面向对象的方法程序,只需要在主函数定义一个变量,直接调用这个变量项目下的程序即可进行对其他数据的操作。面向对象还有三个特性,封装,继承,多态。其中学习的封装,就是封闭的程序,也就是把客观的事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的则进行信息隐蔽。

相关内容

热门资讯

原创 新... 高昌古镇佛龛千载,葡萄美酒踏歌来!提起这片神奇的土地——新疆,无数人脑海中便会浮现出晶莹剔透的葡萄干...
女人想气血好,光吃红枣可不行!... 1、红豆桂圆芋头粥! 2、糯叽叽的姜枣膏! 3、百合紫薯银耳羹!
吕文扬的永安亚博之行 初春的清晨,吕文扬踏上了前往永安市的列车。车窗外的景色如流动的画卷,从都市的钢筋铁骨逐渐过渡到郊野的...
传祺向往S7智趣露营节广州站开... 5月31日,广汽传祺“向往S7智趣家庭露营节”在广州举行。活动以“自然探索+科技体验”为核心,吸引数...
单房造价再次刷新!看城市便捷4... 2025上半年的酒店业,可谓是喜忧参半。一边是大量高端酒店被折价甩卖,挂牌拍卖的数量越来越多,但半数...
向往的生活 传祺向往S7智趣家... 以露营之名,探寻人生每一种与众不同的意义,6月1日,在这个充满活力的初夏,【向往的生活 传祺向往S7...
新场景新业态层出不穷 文旅“玩... 来源:央视网央视网消息: 这个端午假期,形式丰富的文化演出在满足群众假日文化需求的同时,也为文旅融合...
河南人的鱼头酒,从头到尾108... 在河南的酒桌文化中,有一种极具特色的饮酒习俗——“鱼头酒”,甚至衍生出“鱼头酒108杯”的说法。 这...
家常炖燕鱼:简单美味,轻松享受... 在家里做饭,很多人都会追求简单又美味的菜肴。今天,我想和大家分享一种简单易学的炖燕鱼的家常做法。燕鱼...
不是鱼却很补脑,这个优质蛋白被... ⚬ 小管鱿鱼(北方人称其为“海兔”“笔管”)——这种细长如火箭的夏日小海鲜,蛋白质堪比牛肉,脂肪却不...
“水果夹酸奶”风靡长沙,湘菜馆... 文/视频 三湘都市报全媒体记者 仝若楠 继“干噎酸奶”火爆全网后,“水果夹酸奶”又成为近期又一出圈甜...
2025年零食饮料趋势白皮书-... 今天分享的是:2025年零食饮料趋势白皮书-Flywheel飞未 报告共计:90页 《2025年零食...
恒顺健康新品闪耀大阪世博 非遗... 扬子晚报网6月2日讯(通讯员 杨永忠 王娜 记者 万凌云) 端午节前,2025年日本大阪世博会中国馆...
中国十大硬菜 要说中国菜里那些镇得住场子的"硬角色",可不是随便什么菜都能上榜的。这些硬菜要么得有排面,要么得有功...
苏州柏悦酒店五周年庆典:四城名... 为庆祝苏州柏悦酒店开业五周年,一场以“吾载岁悦”为主题的美食美酒晚宴于5月29日璀璨开幕。晚宴特邀知...
潮声丨旅居的魅力,哪里最知道? 潮新闻客户端 执笔 陶韬 去“有风的地方”吹散疲惫,去“有水的村寨”肆意欢笑,到“有篝火的村庄”围炉...
魅力潮汕五日游攻略:探索潮汕旅... 潮汕五日,邂逅山海人文之美 在祖国大陆的南端,有一片神奇而迷人的土地——潮汕。这里,湛蓝的海水与金...
端午假期,阳江这里热!热!热! 今年端午假期恰逢儿童节 传统文化与童趣时光的奇妙邂逅 为海陵岛旅游市场注入全新活力 随着“传统文化+...
游客拍到九寨沟6月飘雪,导游:... 极目新闻记者 谢茂 6月2日,多位前往四川九寨沟旅游的游客发视频称,前往景区途中偶遇下雪,景色绝美。...