欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > C++快速理解之面向对象

C++快速理解之面向对象

2025/4/20 0:20:39 来源:https://blog.csdn.net/qq_44114055/article/details/140825680  浏览:    关键词:C++快速理解之面向对象

文章目录

    • 1、定义类
    • 2、创建对象
    • 3、 使用 . 访问成员
    • 4、使用 ->访问成员
    • 5、this 指针
    • 6、构造函数
    • 7、析构函数
    • 8、重载

对象

C++ 中的类(Class)可以看做C语言中结构体(Struct)的升级版
类是一个通用的概念,C++、Python、C#、PHP 等很多编程语言中都支持类,都可以通过类创建对象

C++、Python、C#、PHP 等语言都支持类和对象,所以使用这些语言编写程序也被称为面向对象编程,这些语言也被称为面向对象的编程语言

C语言因为不支持类和对象的概念,被称为面向过程的编程语言

在C语言中,我们会把重复使用或具有某项功能的代码封装成一个函数,将拥有相关功能的多个函数放在一个源文件,再提供一个对应的头文件,这就是一个模块,使用模块时,引入对应的头文件就可以

在 C++ 中,多了一层封装,就是类(Class)。类由一组相关联的函数、变量组成,你可以将一个类或多个类放在一个源文件,使用时引入对应的类就可以

面向对象编程在代码执行效率上绝对没有任何优势,它的主要目的是方便程序员组织和管理代码,快速梳理编程思路,带来编程思想上的革新
面向对象编程是针对开发中大规模的程序而提出来的,目的是提高软件开发的效率
不要把面向对象和面向过程对立起来,面向对象和面向过程不是矛盾的,而是各有用途、互为补充的。如果你希望开发一个贪吃蛇游戏,类和对象或许是多余的,几个函数就可以搞定;但如果开发一款大型游戏,绝对离不开面向对象

============
类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量

创建对象的过程也叫类的实例化,每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数

与结构体一样,类只是一种复杂数据类型的声明,不占用内存空间;
而对象是类这种数据类型的一个变量,或者说是通过类这种数据类型创建出来的一份实实在在的数据,所以占用内存空间

1、定义类

class Student{
public:// 成员变量char *name;int age;float score;// 成员函数void say(){cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;}
};

{ }内部是类所包含的成员变量和成员函数,它们统称为类的成员(Member)
在类定义的最后有一个分号 ; 它是类定义的一部分,表示类定义结束了,不能省略
class是 C++ 中新增的关键字,专门用来定义类
public也是 C++ 的新增关键字,它只能用在类的定义中,表示类的成员变量或成员函数具有“公开”的访问权限
类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了

2、创建对象

Student leijun;  // 创建对象
class Student leijun;  // 正确,class关键字可要可不要,但是出于习惯我们通常会省略掉 class 关键字
Student leijun;  // 同样正确

除了创建单个对象,还可以创建对象数组:

Student stus[100];

该语句创建了一个 stus 数组,它拥有100个元素,每个元素都是 Student 类型的对象

3、 使用 . 访问成员

#include <iostream>using namespace std;// 类通常定义在函数外面
class Student {
public:// 成员变量char *name;int age;float score;// 成员函数void say() {cout << name << "的年龄是" << age << ",成绩是" << score << endl;}
};int main() {// 创建对象Student boy;// 通过.可以使用对象中的成员boy.name = "小明";boy.age = 15;boy.score = 92.5f;boy.say();// 创建对象2Student girl;// 通过.可以使用对象2中的成员girl.name = "菲菲";girl.age = 18;girl.score = 88.7f;girl.say();return 0;
}

4、使用 ->访问成员

C语言中经典的指针在 C++ 中仍然广泛使用,尤其是指向对象的指针
上面代码中创建的对象 boy在栈上分配内存,需要使用&获取它的地址,例如:

Student boy;
Student *pStu = &boy;

pStu 是一个指针,它指向 Student 类型的数据,也就是通过 Student 创建出来的对象

当然,你也可以在堆上创建对象,这个时候就需要使用前面讲到的new关键字,例如:

Student *pStu = new Student;

通过 new 创建出来的对象,它在堆上分配内存,没有名字,必须使用一个指针变量来接收这个指针,否则以后再也无法找到这个对象了,更没有办法使用它

内存是程序自动管理的
内存由程序员管理,对象使用完毕后需要用 delete 删除

#include <iostream>using namespace std;class Student {
public:char *name;int age;float score;void say() {cout << name << "的年龄是" << age << ",成绩是" << score << endl;}
};int main() {// 创建1个对象,让pStu这个指针变量指向它Student *pStu = new Student;// 既然pStu指向了一个对象(内存空间),那么就可以调用这个内存空间中的某个成员pStu->name = "小明";pStu->age = 15;pStu->score = 92.5f;// 当然也可以调用它里面的函数pStu->say();// 当不要pStu指向的对象时,需要用delete进行删除(就是释放那个内存空间)delete pStu;//对不再使用的对象,记得用 delete 进行回收空间,这是一种良好的编程习惯return 0;
}

代码运行visual studio 2022:
错误记录:不能将 “const char *“ 类型的值分配到 “char“ 类型的实体问题
在这里插入图片描述

在这里插入图片描述

解决方法:

在声明p指针指向char数组的时候 前面要加const 不然就会报错
在这里插入图片描述

5、this 指针

#include <iostream>using namespace std;class Student {
public:char *name;int age;float score;void say() {//如果在成员函数中使用name,此时name没有在say函数中定义//那么就会往前找这个name函数,此时发现找到了成员变量namecout << name << "的年龄是" << age << ",成绩是" << score << endl;}void setNewAgeScore(int ageTemp, float scoreTemp) {age = ageTemp;score = scoreTemp;}void setNewAgeScore2(int age, float score) {age = age;score = score;//在每个成员函数中直接使用,他是在编译的时候自动添加的,他指向了当前对象自己,类似python中的self}
};int main() {// 创建一个对象Student *pStu = new Student;// 调用对象的成员变量pStu->name = "小明";pStu->age = 15;pStu->score = 92.5f;// 调用对象的成员函数pStu->say();// 设置新的年龄、分数pStu->setNewAgeScore(16, 98.66f);pStu->say();pStu->setNewAgeScore2(17, 96.75);pStu->say();delete pStu;  //删除对象return 0;
}

上面代码结果:
在这里插入图片描述
为什么第3次的设置年龄与分数没有起作用呢?

void setNewAgeScore2(int age, float score) {
//首先,整体是一个赋值语句,会将=右侧限制性,即将age这个局部变量的值取出来,17,this->age=17
//既然=右侧已经计算完毕,那么就将这个结果,放到=左侧变量中
//=左侧 又是1个较复杂的计算,this->age,她先用this
//此时this指向一个对象this->age = age;this->score = score;//在每个成员函数中直接使用,他是在编译的时候自动添加的,他指向了当前对象自己,类似python中的self}

this 是 C++ 中的一个关键字,它指向当前对象,通过它可以访问当前对象的所有成员

说的直白一点:在成员函数被调用的过程中,会自动生成1个this指针变量,它指向当前调用对象自己,因此可以直接使用this->操作成员变量与成员函数

this 实际上是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 this。不过 this 这个形参是隐式的,它并不出现在代码中,而是在编译阶段由编译器默默地将它添加到参数列表中

地址关系:

#include <iostream>using namespace std;class Student {
public:void printThis() {cout << this << endl;}
};int main() {Student *pStu1 = new Student;pStu1->printThis();cout << pStu1 << endl;cout << "------------------\n";Student *pStu2 = new Student;pStu2->printThis();cout << pStu2 << endl;delete pStu1;  //删除对象delete pStu2;  //删除对象return 0;
}

在这里插入图片描述
PS:
记录问题

&pStu 和 *pStu 的地址是不一样的。
&pStu 表示的是指针 pStu 本身在内存中的地址。
*pStu 表示的是通过指针 pStu 所指向的 Student 类型的对象。
例如,如果 pStu 存储的地址是 0x1234 ,那么 &pStu 就是 pStu 这个指针变量在内存中的地址,比如 0x5678 ,而 *pStu 表示的是位于 0x1234 处的 Student 对象。

6、构造函数

构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行

怎样定义?
与类名同名没有返回值,可以被重载

有什么用?
通常用来做初始化工作

7、析构函数

一种在对象销毁时,自动调用的函数

怎样定义?
析构函数名称与类名称相同,只是在前面加了个波浪号 ~ 作为前缀,它不会返回任何值,也不能带有任何参数,不能被重载

有什么用?
一般用于释放资源,例如关闭打开的文件,打开的网络socket套接字等

#include <iostream>
#include <string>using namespace std;class Student {
public :char *name;int age;// 构造函数Student() {cout << "执行无参构造函数" << endl;}Student(char *name) {cout << "执行含有一个参数的参构造函数" << endl;}Student(char *name, int age) {cout << "执行含有两个参数的构造函数" << endl;}// 析构函数~Student() {cout << "执行析构函数" << endl;}
};
int main() {// 创建对象时,自动调用构造函数Student *pStu1 = new Student;Student *pStu2 = new Student;Student *pStu3 = new Student;// 销毁对象时,自动调用析构函数delete pStu1;delete pStu2;delete pStu3;return 0;
}

在这里插入图片描述

8、重载

函数名相同,形参不同,调用的时候会自动调对应的

案例:

目的:了解怎样让多个对象之间如何产生关联,从而实现发挥面向对象编程的威力

错误记录:
1没有与参数列表匹配的构造函数
构造函数里的参数定义要与成员变量一致

#include <iostream>
using namespace std;class Gun {
public:const char* name;Gun(const char* name) { // 添加构造函数this->name = name;}const char* get_name() {return this->name;}void display_info() {cout << "name:" << this->name << "\n";}
};class Bullet {
public:int kill_power;Bullet(int kill_power) {this->kill_power = kill_power;}void display_info() {cout << "子弹的威力值:" << this->kill_power << "\n";}
};class Person {
public:const char *name;Gun* gun;Person(const char *name) {this->name = name;}void display_info() {cout << "name:" << this->name << "\n";}void get_gun(Gun* gun) {this->gun = gun;cout << this->name << " 拿起了" << gun->get_name() << "\n";}};int main(){class Person hero("钢铁侠");hero.display_info();class Gun gun("AK47");gun.display_info();hero.get_gun(&gun);return 0;
}

在这里插入图片描述

#include <iostream>
using namespace std;class Bullet {
public:int kill_power;Bullet(int kill_power) {this->kill_power = kill_power;}void display_info() {cout << "子弹的威力值:" << this->kill_power << "\n";}int get_power() {return this->kill_power;}
};class Gun {
public:const char* name;Bullet* bullet;Gun(const char* name) { // 添加构造函数this->name = name;}const char* get_name() {return this->name;}void display_info() {cout << "name:" << this->name << "\n";}void install_bullet(Bullet* bullet) {this->bullet = bullet;cout << this->name << " 已经安装子弹\n";}
};class Person {
public:const char *name;Gun* gun;Bullet* bullet;Person(const char *name) {this->name = name;}void display_info() {cout << "name:" << this->name << "\n";}void get_gun(Gun* gun) {this->gun = gun;cout << this->name << " 拿起了" << gun->get_name() << "\n";}void get_bullet(Bullet *bullet) {this->bullet = bullet;cout << this->name << " 拿起了子弹,威力是:" << bullet->get_power() << "\n";}void install_bullet_to_gun() {this->gun->install_bullet(this->bullet);}};int main(){class Person hero("钢铁侠");hero.display_info();class Gun gun("AK47");gun.display_info();class Bullet bullet(10);bullet.display_info();hero.get_gun(&gun);hero.get_bullet(&bullet);hero.install_bullet_to_gun();return 0;
}

在这里插入图片描述
注意:
一开始Gun类的定义在Bullet类的定义之前,但是它使用了Bullet类。这会导致编译器无法识别Bullet类。我们需要提前声明Bullet类。
另外,确保所有指针变量在使用之前已经正确初始化。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词