【C++】类和对象(一)

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

  • 导读
  • 1. 面向对象
  • 2. 类
    • 2.1 类的定义
  • 3. 类的访问限定符
  • 4. class与struct定义类的区别
  • 5. 类的封装
  • 6. 类的作用域
  • 7.类的实例化
  • 8. 类的存储方式
  • 9. this指针
  • 10. 题目思考

导读

前面我们学习了C++的入门基础,感兴趣的小伙伴可以点击上方的“C++学习”专栏。今天我们一起来学习类和对象,本篇文章重点了解类。

1. 面向对象

C++是一种面向对象的编程语言,面向对象编程(OOP)是一种软件开发方法,其中程序被组织为对象的集合,这些对象通过相互之间的通信来完成任务。
比如我们洗衣服:

  1. 将衣服放入洗涤桶,倒入适量水与洗衣液,开启定时开关。
  2. 洗衣机定时关闭后放入清水中清掉泡沫放入脱水机中定时脱水。
  3. 脱水完成后拿出衣服即可。

在这里插入图片描述
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

总共有四个对象:人,洗衣机,衣服,洗衣液。
整个过程是四个对象之间交互完成的,人不需要关注洗衣机是如何洗衣甩干的。

在这里插入图片描述

2. 类

类是一种自定义的数据类型,可以定义多个对象(实例)来访问类的成员。类的成员可以是变量(数据成员)或函数(成员函数),用于表示对象的状态和行为。

2.1 类的定义

要定义一个类,需要使用关键字class,然后在类体内定义数据成员和成员函数。类体内也可以定义构造函数、析构函数、访问控制修饰符(public、private、protected)等。

class className
{
// 类体:由成员函数和成员变量组成
};
// 一定要注意后面的分号

在定义类中:

  1. 我们可以把声明和定义全部放在类体中。

需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。

class Person {
public:Person(string name, int age) {this->name = name;this->age = age;}void display() {cout << "Name: " << name << endl;cout << "Age: " << age << endl;}string name;int age;
};int main() {// 创建一个Person对象Person p("Alice", 25);// 调用成员函数display显示对象的信息p.display();return 0;
}
  1. 类声明放在.h文件中,成员函数定义放在.cpp文件中。

注意:成员函数名前需要加类名::

一般情况下,更期望采用第二种方式。
今天为了方便理解,我们采用第一种方式。

3. 类的访问限定符

在C++中,类的成员可以通过访问限定符来控制其对外部的可见性和访问权限,以确保数据的安全性和封装性。

class MyClass {private:int privateVar;public:int publicVar;protected:int protectedVar;
};

在这里插入图片描述

  1. public访问限定符:被声明为public的成员可以在类的内部和外部被访问。

  2. private访问限定符:被声明为private的成员只能在类的内部被访问,外部代码无法直接访问。

  3. protected访问限定符:被声明为protected的成员在类的内部可以被访问,并且在派生类中也可以被访问。

  4. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止

  5. 如果后面没有访问限定符,作用域就到}即类结束。

  6. class的默认访问权限为private,struct为public(因为struct要兼容C)

4. class与struct定义类的区别

在C++中,class和struct都可以用于定义自定义的数据类型,即用户自定义的数据结构。它们的主要区别在于默认的成员访问限定符和默认的继承访问限定符。

在class中,默认的成员访问限定符是private。在struct中,默认的成员访问限定符是public。

class MyClass {int privateVar;   // 默认为privatepublic:int publicVar;void myFunction() {// 在类的内部可以访问private和public成员privateVar = 10;publicVar = 20;}
};struct MyStruct {int publicVar;    // 默认为publicprivate:int privateVar;void myFunction() {// 在结构体的内部可以访问private和public成员privateVar = 10;publicVar = 20;}
};int main() {MyClass myClassObj;myClassObj.publicVar = 30;   // 可以直接访问public成员MyStruct myStructObj;myStructObj.publicVar = 40;  // 可以直接访问public成员return 0;
}

5. 类的封装

面向对象的三大特性:封装、继承、多态。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。

class Circle {
private:double radius;  // 封装的数据public:// 公共接口void setRadius(double r) {if (r >= 0)radius = r;}double getRadius() {return radius;}double calculateArea() {return 3.14 * radius * radius;}
};int main() {Circle c;c.setRadius(5.0);       // 通过公共接口设置半径double area = c.calculateArea();   // 通过公共接口计算面积return 0;
}

在上面的例子中,类Circle封装了一个私有的成员变量radius,并提供了公共的方法setRadius、getRadius和calculateArea来设置半径、获取半径和计算面积。
外部代码无法直接访问和修改radius,只能通过公共接口来操作。这样可以保证radius的有效性和数据的一致性,并提供了简洁的接口来操作数据。

6. 类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。

class Person {
private:string name;int age;public:Person(string name, int age) {this->name = name;this->age = age;}void display();};
// 这里需要指定display是属于Person这个类域
void Person::display()
{cout << "Name: " << name << endl;cout << "Age: " << age << endl;
}
int main() {// 创建一个Person对象Person p("Alice", 25);// 调用成员函数display显示对象的信息p.display();return 0;
}

7.类的实例化

在C++中,类的实例化是通过创建对象来实现的。
如下述代码中,Person类是没有空间的,只有Person类实例化出的对象才有具体的物理空间。

class Person {
private:string name;int age;public:Person(string name, int age) {this->name = name;this->age = age;}void display(){cout << "Name: " << name << endl;cout << "Age: " << age << endl;}};int main() {// 创建Person类对象Person p("Alice", 25);// 调用成员函数display显示对象的信息p.display();return 0;
}

8. 类的存储方式

只保存成员变量,成员函数存放在公共的代码段
在这里插入图片描述

9. this指针

C++中的this指针是一个隐含的指针,指向当前对象的地址。它可以在类的成员函数中使用,用来访问当前对象的成员变量和成员函数。
比如:

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1, d2;d1.Init(2024, 1, 30);d2.Init(2022, 1, 29);d1.Print();d2.Print();return 0;
}

Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

:C++编译器给每个“非静态的成员函数“增加了一个隐藏
的指针参数,也就是this指针。
让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。
只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

this指针的使用有以下几个特点:

  1. 在类的非静态成员函数中,this指针被自动地传入函数中,无需显式地声明。可以通过this指针来访问当前对象的成员变量和成员函数。例如,如果在一个成员函数中想要访问成员变量x,可以使用this->x。

  2. this指针是一个常量指针,不能被修改,即不能对this指针进行赋值操作。

  3. this指针可以在成员函数中使用,也可以在成员函数外部使用。在成员函数外部使用时,需要通过对象名来访问this指针,例如obj->this。

  4. 在类的静态成员函数中,由于静态成员函数不属于任何对象,所以不能使用this指针。静态成员函数只能访问静态成员变量和其他静态成员函数。

10. 题目思考

  1. 下面程序编译运行结果是?
    A、编译报错 B、运行崩溃 C、正常运行
class A
{public:void Print(){cout << "Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}

正常运行

p不发生解引用,因为成员函数的地址不存在对象中,在公共代码区域。这里p为空指针传入print中,然后this接受print地址直接输入。

  1. 下面程序编译运行结果是?
    A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->PrintA();return 0;
}

运行崩溃:前面一样,this接受的是_a,因为-a是成员变量会对print的p进行解引用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/439930.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言菜鸟入门·判断语句(if语句、if...else语句、嵌套if语句)详细介绍

目录 1. if语句 2. if...else语句 3. if...else if...else 语句 4. 嵌套if语句 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 false。 语句描述if语句一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。if...else语句一个 if 语句 后可跟…

MySQL解决 恢复从备份点到灾难点之间数据(不收藏找不到了)

CSDN 成就一亿技术人&#xff01; 今天分享一期 mysql中 备份之后发生灾难造成数据丢失 那么如何恢复中间的数据呢&#xff1f; 数据库数据高于一切&#xff08;任何数据是不能丢失的&#xff09; CSDN 成就一亿技术人&#xff01; 目录 1.准备测试数据库 2.备份数据库 观…

vue 使用 v-viewer 用于图片浏览的Vue组件,支持旋转、缩放、翻转等操作,基于viewer.js。

作者连接 npm&#xff1a; npm install v-viewerlegacy viewerjs main.js 引入&#xff1a; // 引入Viewer插件 import VueViewer, { directive as viewerDirective } from v-viewer; // 引入Viewer插件的图片预览器的样式 import viewerjs/dist/viewer.css; // 使用Viewer图片…

动手学RAG:汽车知识问答

原文&#xff1a;动手学RAG&#xff1a;汽车知识问答 - 知乎 Part1 内容介绍 在自然语言处理领域&#xff0c;大型语言模型&#xff08;LLM&#xff09;如GPT-3、BERT等已经取得了显著的进展&#xff0c;它们能够生成连贯、自然的文本&#xff0c;回答问题&#xff0c;并执行…

SSE长连接( SpringBoot整合SSE(Server-Sent Events)可以实现后端主动向前端推送数据)

Demo代码分享 依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.or…

记录一次腾讯云服务器部署宝塔

一、查看是否安装 宝塔面板 bt 14 1 已安装会列出宝塔登录地址&#xff1b; 否则-bash: bt: command not found&#xff1b; 下载及安装命令&#xff08;这条是目前最新的宝塔安装命令&#xff09; yum install -y wget && wget -O install.sh http://download.bt.cn/…

常见的网络安全威胁和防护方法

随着数字化转型和新兴技术在各行业广泛应用&#xff0c;网络安全威胁对现代企业的业务运营和生产活动也产生了日益深远的影响。常见的网络安全威胁通常有以下几种&#xff1a; 1. 钓鱼攻击 攻击者伪装成合法的实体&#xff08;如银行、电子邮件提供商、社交媒体平台等&#xf…

ASPICE--汽车行业过程评估/参考模型

近几年&#xff0c;汽车行业飞速发展&#xff0c;尤其是是新能源汽车&#xff0c;试图完全颠覆传统汽车行业的风格&#xff0c;多家企业喊出“软件定义汽车”“软件智能一体化”等类似的口号。由此可见&#xff0c;软件在新类型的汽车设计中占有独一无二的领导地位&#xff0c;…

【webrtc】‘ninja.exe‘ 不是内部或外部命令,也不是可运行的程序及vs2019 重新构建m98

werbtc 就是用ninja.exe 来构建找到了自己以前构建的webrtc 原版 m98 【m98 】webrtc ninja 构建 、example、tests 及OWT- P2P 项目P2PMFC-E2E-m98G:\CDN\rtcCli\webrtc-checkout\src找到了自己的deptools的路径 deptools里确实没有ninja.exe D:\SOFT\depot_tools\third_party…

【Django开发】前后端分离美多商城项目:项目准备和搭建(附代码,文档)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论django商城项目开发相关知识。本项目利用Django框架开发一套前后端不分离的商城项目&#xff08;4.0版本&#xff09;含代码和文档。功能包括前后端不分离&#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现…

考研经验总结——英语篇

文章目录 一、前言二、刷题情况三、关于背诵四、建议五、大作文模板作文词汇一、图画类作文1.1 para.1 description 远景近景&#xff08;倒装分词结构&#xff09;1.2 para.2 interpretation (两正一反或一正一反)1.3 para.3 comment 二、柱线饼表2.1 line chart 双柱对比图线…

课时8:shell基础_shell实践

1.3.2 shell实践 学习目标 这一节&#xff0c;我们从 shell分类、shell实践、小结 三个方面来学习。 shell分类 简介 在不同的操作系统上&#xff0c;shell的表现样式是不一样的&#xff0c;按照我的角度&#xff0c;它主要分为两类 图形界面shell图形界面shell就是我们常…