C++————类和对象(一)
1.类定义格式
在C++中,类(class)是封装数据和操作这些数据的函数的构造。类的定义包含成员变量和成员函数。
类的基本定义格式如下:
class ClassName {// 访问修饰符public:// 公有成员DataType memberVariable; // 成员变量void memberFunction() { // 成员函数// 函数体}private:// 私有成员(可选)DataType privateVariable;protected:// 受保护成员(可选)DataType protectedVariable;
- 成员变量:类中用于存储数据的变量,数据类型由
DataType表示。 - 成员函数:类中的函数,可以操作类的成员变量。
示例:
#include <iostream>
using namespace std;class Car {
public:string brand; // 公有成员变量int year;// 公有成员函数void start() {cout << "The car is starting." << endl;}
};int main() {// 创建对象Car myCar;// 访问对象的成员myCar.brand = "Toyota";myCar.year = 2021;cout << "Brand: " << myCar.brand << ", Year: " << myCar.year << endl;myCar.start(); // 调用成员函数return 0;
}
- 为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前面或者后面加_或者m 开头。
示例代码:
使用 _ 前缀:
cpp
#include <iostream>
using namespace std;class Car {
public:string _brand; // 使用 _ 前缀作为成员变量的标识int _year;void start() {cout << "The car is starting." << endl;}
};int main() {Car myCar;myCar._brand = "Toyota";myCar._year = 2021;cout << "Brand: " << myCar._brand << ", Year: " << myCar._year << endl;myCar.start();return 0;
}
这些做法有助于提高代码的可读性,尤其是在类中存在多个变量时,能够快速识别出哪些是成员变量,可以帮助提高代码的清晰度,尤其是在较大的项目中。
- C++中struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类,明显的变化是 struct中可以定义函数,⼀般情况下我们还是推荐用class定义类。
#include<iostream>
using namespace std;
// C++升级struct升级成了类// 1、类⾥⾯可以定义函数// 2、struct名称就可以代表类型// C++兼容C中struct的⽤法typedef struct ListNodeC
{struct ListNodeC* next;int val;
}LTNode;
// 不再需要typedef,ListNodeCPP就可以代表类型struct ListNodeCPP
{void Init(int x){next = nullptr;val = x;}ListNodeCPP* next;int val;
};int main()
{return 0;
}
- 定义在类面的成员函数默认为inline
在 C++ 中,类内定义的成员函数默认是 inline 的。这意味着,如果成员函数的实现出现在类的定义内部,编译器通常会尝试将该函数进行内联替换。
这也有一些好处:
- 减少函数调用开销:通过将函数的代码直接插入到调用的地方,避免了传统的函数调用机制(如栈操作、跳转等)的开销。
- 适用于短小函数:
inline通常适用于小型函数,尤其是成员函数。如果函数体非常简单,编译器会倾向于将其内联。
1.1 访问限定符
在 C++ 中,访问限定符(Access Specifiers) 用于控制类的成员(包括数据成员和成员函数)在类外部的访问权限。C++ 中有三种主要的访问限定符:public、private 和 protected。这些限定符决定了类的成员在类外如何被访问。
1.1.1 public
- 描述:
public成员是最宽松的,它允许类的外部代码访问这些成员。 - 适用场景:通常用于希望外部能够直接访问或修改的数据成员和成员函数,例如提供接口方法、获取和设置数据等。
示例:
class MyClass {
public:int publicValue; // 公有成员void display() { // 公有成员函数std::cout << "Public value: " << publicValue << std::endl;}
};int main() {MyClass obj;obj.publicValue = 10; // 可以直接访问公有成员obj.display(); // 可以直接调用公有成员函数return 0;
}
1.1.2 private
- 描述:
private成员只能在类的内部访问,类的外部无法直接访问这些成员。即便是派生类也不能访问基类的private成员。 - 适用场景:通常用于将类的内部实现细节隐藏起来,防止外部代码直接修改,确保数据封装和类的安全性。
示例:
class MyClass {
private:int privateValue; // 私有成员public:void setValue(int value) { // 公有成员函数,用于修改私有成员privateValue = value;}void display() {std::cout << "Private value: " << privateValue << std::endl;}
};int main() {MyClass obj;// obj.privateValue = 10; // 错误,不能直接访问私有成员obj.setValue(10); // 可以通过公有成员函数间接访问obj.display();return 0;
}
1.1.3 protected
- 描述:
protected成员既不能被类外部访问,也不能被外部对象直接访问。但是,派生类可以访问基类的protected成员(但不能被外部直接访问)。因此,protected成员适用于希望在类的外部隐藏,但允许派生类访问的成员。 - 适用场景:通常用于需要继承的类中,提供一个在派生类中可访问的成员。
protected 与 private 的区别
private成员只能在类的成员函数内部访问,派生类和外部代码都无法直接访问。protected成员只能在类的成员函数和派生类中访问,外部代码不能访问。
示例:
#include <iostream>
using namespace std;class Base {
protected:int protectedValue; // 保护成员public:Base() : protectedValue(0) {}void setProtectedValue(int value) {protectedValue = value;}void display() {cout << "Protected value: " << protectedValue << endl;}
};class Derived : public Base {
public:void modify() {protectedValue = 100; // 派生类可以访问基类的保护成员}
};int main() {Base baseObj;baseObj.setProtectedValue(10);baseObj.display(); // 输出: Protected value: 10Derived derivedObj;derivedObj.modify();derivedObj.display(); // 输出: Protected value: 100// baseObj.protectedValue = 200; // 错误,不能访问保护成员// std::cout << baseObj.protectedValue << endl; // 错误,不能直接访问保护成员return 0;
}
1.1.4 成员的默认访问级别
- 如果在类中没有指定访问级别:
- 在
class中,默认是private。 - 在
struct中,默认是public。
- 在
示例:
class MyClass {int value; // 默认是 private
};struct MyStruct {int value; // 默认是 public
};
//有遗漏的地方,再后续的类和对象的学习中会有补充!
1.2.类域
- 类定义了⼀个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
- 类域影响的是编译的查找规则,下⾯程序中Init如果不指定类域Stack,那么编译器就把Init当成全 局函数,那么编译时,找不到array等成员的声明/定义在哪里,就会报错。指定类域Stack,就是知 道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。
#include<iostream>
using namespace std;
class Stack
{
public://成员函数void Init(int n = 4);
private:// 成员变量int* array;size_t capacity;size_t top;
};
// 声明和定义分离,需要指定类域void Stack::Init(int n)
{array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申请空间失败");return;}capacity = n;top = 0;
}
int main()
{Stack st;st.Init();return 0;
}
2. 实例化
在 C++ 中,实例化(Instantiation)指的是根据一个类(class)的定义创建一个具体的对象。通过实例化,我们可以生成类的具体对象并在内存中分配空间。这个过程使得类变成可以操作和使用的实体。
2.1实例化的过程
实例化实际上是将类作为模板,创建出类的对象。对象是类的实例,它拥有类定义的属性和行为。实例化过程分为两个主要步骤:
- 定义类:类是一个模板,包含成员变量(属性)和成员函数(方法),它只是一个概念上的蓝图。
- 创建对象:通过类定义创建一个对象,分配内存并初始化对象的成员变量。
2.2 实例化的举例
假设我们有一个简单的 Car 类,定义了车的属性(如颜色和速度)以及行为(如启动和停车)。
2.2.1 类的定义
class Car {
public:// 成员变量string color;int speed;// 构造函数Car(string c, int s) : color(c), speed(s) {}// 成员函数void start() {cout << "The car is starting." << endl;}void stop() {cout << "The car is stopping." << endl;}
};
在这个类定义中,Car 类具有成员变量 color 和 speed,以及成员函数 start() 和 stop()。
2.2.2 实例化对象
实例化对象就是根据类模板创建出一个具体的对象。在 main 函数中,我们实例化了一个 Car 对象。
int main() {Car myCar("Red", 100); // 实例化 Car 类对象 myCarmyCar.start(); // 调用 myCar 对象的 start 函数cout << "The color of the car is: " << myCar.color << endl; // 输出 car 的颜色return 0;
}
在这个代码片段中,Car myCar("Red", 100); 就是实例化过程,我们创建了一个名为 myCar 的对象,它是 Car 类的一个实例。myCar 被初始化为红色,并且速度为 100。
myCar.start(); 和 myCar.color 展示了如何使用实例化出来的对象。
2.3 对象大小
在C++中,实例化对象时涉及到对象的大小,这个大小是由对象中包含的成员变量(数据成员)决定的。我们可以通过对对象大小的了解,进一步优化程序的内存管理。
- 第⼀个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
- 注意:对齐数=编译器默认的⼀个对齐数与该成员大小的较⼩值。
- VS中默认的对齐数为8
- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小 就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
结构体对齐示例
#include <iostream>
using namespace std;struct Example {char c; // 1 字节int i; // 4 字节
};int main() {cout << "Size of Example: " << sizeof(Example) << " bytes" << endl;return 0;
}
输出可能为:
Size of Example: 8 bytes
3. this指针
在 C++ 中,this 指针是一个隐式存在的指针,指向当前对象的地址。它是类的成员函数在调用时自动提供的指针,可以用来访问当前对象的成员变量和成员函数。
this 指针的特点:
- 隐式传递:
this指针是由编译器自动传递给成员函数的,你不需要显式传递它。 - 指向当前对象:
this指针指向调用该成员函数的对象本身。因此,它可以用于访问当前对象的成员变量和成员函数。 - 常量指针:
this指针是一个常量指针,意味着你不能改变它指向的对象。例如,this = some_object;是不允许的。 - C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。
- 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this 指针。
- 类的成员函数中访问成员变量,本质都是通过this指针访问的
this 指针的使用场景:
区分成员变量和函数参数名冲突: 如果成员函数的参数名与成员变量相同,可以通过 this 指针来区分。
class MyClass {
private:int value;
public:void setValue(int value) {this->value = value; // 使用 this 指针来区分成员变量和参数}
};
相关文章:
C++————类和对象(一)
1.类定义格式 在C中,类(class)是封装数据和操作这些数据的函数的构造。类的定义包含成员变量和成员函数。 类的基本定义格式如下: class ClassName {// 访问修饰符public:// 公有成员DataType memberVariable; // 成员变量voi…...
SpringBoot参数校验:@Valid 与 @Validated 详解
SpringBoot参数校验:Valid 与 Validated 详解 一、案例(参数校验的必要性) 传统方式(无注解)的缺点: // 需要手动校验每个字段,代码冗余且易出错 public String register(User user) {// 手动…...
<论文>MiniCPM:利用可扩展训练策略揭示小型语言模型的潜力
一、摘要 本文跟大家一起阅读的是清华大学的论文《MiniCPM: Unveiling the Potential of Small Language Models with Scalable Training Strategies》 摘要: 对具有高达万亿参数的大型语言模型(LLMs)的兴趣日益增长,但同时也引发…...
SpringCloud系列教程(十三):Sentinel流量控制
SpringCloud中的注册、发现、网关、服务调用都已经完成了,现在就剩下最后一部分,就是关于网络控制。SpringCloud Alibaba这一套中间件做的非常好,把平时常用的功能都集成进来了,而且非常简单高效。我们下一步就完成最后一块拼图Se…...
Codeforces Round 502 E. The Supersonic Rocket 凸包、kmp
题目链接 题目大意 平面上给定两个点集,判定两个点集分别形成的凸多边形能否通过旋转、平移重合。 点集大小 ≤ \leq ≤ 1 0 5 10^{5} 105,坐标范围 [0, 1 0 8 10^{8} 108 ]. 思路 题意很明显,先求出凸包再判断两凸包是否同构。这里用…...
论文阅读方法
文章目录 步骤一:对论文进行自我判断阅读题目和关键词。阅读摘要阅读总结要点 步骤二:阅读文章阅读图表和图表的注释阅读引言阅读实验部分阅读结果和作者对结果的讨论(创新点)要点 步骤三:精度论文回答问题1回答问题2回…...
ArcGIS操作:15 计算点的经纬度,并添加到属性表
注意:需要转化为地理坐标系 1、打开属性表,添加字段 2、计算字段(以计算纬度为例 !Shape!.centroid.Y ) 3、效果...
蓝桥杯历年真题题解
1.轨道炮(数学模拟) #include <iostream> #include <map> using namespace std; const int N1010; int x[N],y[N],v[N]; char d[N]; int main() {int n;int ans-100;cin>>n;for(int i1;i<n;i)cin>>x[i]>>y[i]>>v…...
IP-地址
主机号(Host ID) IP地址简介:IP地址是每台接入互联网的设备所拥有的唯一标识符,类似于电话号码的分层结构,由网络号和主机号组成。为了便于记忆,32位二进制的IP地址通常以点分十进制表示。 网络号…...
MoonSharp 文档一
目录 1.Getting Started 步骤1:在 IDE 中引入 MoonSharp 步骤2:引入命名空间 步骤3:调用脚本 步骤4:运行代码 2.Keeping a Script around 步骤1:复现前教程所有操作 步骤2:改为创建Script对象 步骤…...
2025-03-08 学习记录--C/C++-PTA 习题10-1 判断满足条件的三位数
合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻 一、题目描述 ⭐️ 裁判测试程序样例: #include <stdio.h> #include <math.h>int search( int n );int…...
三星首款三折叠手机被曝外屏6.49英寸:折叠屏领域的新突破
在智能手机的发展历程中,折叠屏手机的出现无疑是一次具有里程碑意义的创新。它打破了传统手机屏幕尺寸的限制,为用户带来了更加多元和便捷的使用体验。而三星,作为手机行业的巨头,一直以来都在折叠屏技术领域积极探索和创新。近日,三星首款三折叠手机的诸多细节被曝光,其…...
大白话Vue Router 中路由守卫(全局守卫、路由独享守卫、组件内守卫)的种类及应用场景
大白话Vue Router 中路由守卫(全局守卫、路由独享守卫、组件内守卫)的种类及应用场景 答题思路 明确要介绍的内容:需要分别介绍 Vue Router 中全局守卫、路由独享守卫和组件内守卫这三种路由守卫的种类,详细说明它们的定义、使用…...
CUDA编程之OpenCV与CUDA结合使用
OpenCV与CUDA的结合使用可显著提升图像处理性能。 一、版本匹配与环境配置 CUDA与OpenCV版本兼容性 OpenCV各版本对CUDA的支持存在差异,例如OpenCV 4.5.4需搭配CUDA 10.02,而较新的OpenCV 4.8.0需使用更高版本CUDA。 需注意部分模块(…...
Educational Codeforces Round 7 F. The Sum of the k-th Powers 多项式、拉格朗日插值
题目链接 题目大意 求 ( ∑ i 1 n i k ) (\sum_{i1}^{n} i^k) (∑i1nik) m o d ( 1 0 9 7 ) mod(10^97) mod(1097) . 数据范围 : 1 ≤ n ≤ 1 0 9 1 \leq n \leq 10^9 1≤n≤109 , 0 ≤ k ≤ 1 0 6 0 \leq k \leq 10^6 0≤k≤106 . 思路 令 f ( n ) ∑ …...
LINUX网络基础 [五] - HTTP协议
目录 HTTP协议 预备知识 认识 URL 认识 urlencode 和 urldecode HTTP协议格式 HTTP请求协议格式 HTTP响应协议格式 HTTP的方法 HTTP的状态码 编辑HTTP常见Header HTTP实现代码 HttpServer.hpp HttpServer.cpp Socket.hpp log.hpp Makefile Web根目录 H…...
WPS Word中英文混杂空格和行间距不一致调整方案
文章目录 问题1:在两端对齐的情况下,如何删除参考文献(英文)的空格问题2:中英文混杂行间距不一致问题问题3:设置中文为固定字体,设置西文为固定字体参考 问题1:在两端对齐的情况下&a…...
C++ Qt创建计时器
在Qt中,可以使用QTimer来创建一个简单的计时器。QTimer是一个用于定时触发事件的类,通常与QObject的子类(如QWidget)一起使用。以下是一个完整的示例,展示如何使用Qt创建一个带有计时器的窗口应用程序。 示例ÿ…...
CSDN博客:Markdown编辑语法教程总结教程(中)
❤个人主页:折枝寄北的博客 Markdown编辑语法教程总结 前言1. 列表1.1 无序列表1.2 有序列表1.3 待办事项列表1.4 自定义列表 2. 图片2.1 直接插入图片2.2 插入带尺寸的图片2.3 插入宽度确定,高度等比例的图片2.4 插入高度确定宽度等比例的图片2.5 插入居…...
nlp培训重点-5
1. LoRA微调 loader: # -*- coding: utf-8 -*-import json import re import os import torch import numpy as np from torch.utils.data import Dataset, DataLoader from transformers import BertTokenizer """ 数据加载 """cl…...
电子学会—2024年月6青少年软件编程(图形化)四级等级考试真题——水仙花数
水仙花数 如果一个三位数等于它各个数位上的数字的立方和,那么这个数就是水仙花数,例如:153 111 555 333,153就是一个水仙花数。 1.准备工作 (1)保留默认角色小猫; (2)白色背景。 2.功能实现 (1)使用循环遍历所有三位数,把所…...
若依分页的逻辑分析
看了一些网上的感觉都是 听君一席话, 如听一席话. 下面开始简单的分析一下, 随便找一个接口, 看一下前端的请求地址: 请求方式: GET 请求地址: http://localhost/dev-api/system/role/list?pageNum1&pageSize10 后端接口: PreAuthorize("ss.hasPermi(system:role:li…...
JetBrains学生申请
目录 JetBrains学生免费授权申请 IDEA安装与使用 第一个JAVA代码 1.利用txt文件和cmd命令运行 2.使用IDEA新建项目 JetBrains学生免费授权申请 本教程采用学生校园邮箱申请,所以要先去自己的学校申请校园邮箱。 进入JetBrains官网 点击立即申请,然…...
【算法方法总结·五】链表操作的一些技巧和注意事项
【算法方法总结五】链表操作的一些技巧和注意事项 【算法方法总结一】二分法的一些技巧和注意事项【算法方法总结二】双指针的一些技巧和注意事项【算法方法总结三】滑动窗口的一些技巧和注意事项【算法方法总结四】字符串操作的一些技巧和注意事项【算法方法总结五】链表操作…...
langchain系列(终)- LangGraph 多智能体详解
目录 一、导读 二、概念原理 1、智能体 2、多智能体 3、智能体弊端 4、多智能体优点 5、多智能体架构 6、交接(Handoffs) 7、架构说明 (1)网络 (2)监督者 (3)监督者&…...
侯捷 C++ 课程学习笔记:深入理解智能指针
文章目录 每日一句正能量一、引言二、智能指针的核心概念(一)std::unique_ptr(二)std::shared_ptr(三)std::weak_ptr 三、学习心得四、实际应用案例五、总结 每日一句正能量 如果说幸福是一个悖论ÿ…...
访问不了 https://raw.githubusercontent.com 怎么办?
修改 Hosts 文件(推荐) 原理:通过手动指定域名对应的 IP 地址,绕过 DNS 污染。 步骤: 1、访问 IPAddress.com,搜索 raw.githubusercontent.com,获取当前最新的 IPv4 地址(例如 1…...
大模型工程师学习日记(十五):Hugging Face 模型微调训练(基于 BERT 的中文评价情感分析)
1. datasets 库核心方法 1.1. 列出数据集 使用 d atasets 库,你可以轻松列出所有 Hugging Face 平台上的数据集: from datasets import list_datasets# 列出所有数据集 all_datasets list_datasets()print(all_datasets)1.2. 加载数据集 你可以通过 l…...
Codeforces Round 258 (Div. 2) E. Devu and Flowers 生成函数
题目链接 题目大意 有 n n n ( 1 ≤ n ≤ 20 ) (1\leq n \leq 20) (1≤n≤20) 个花瓶,第 i i i 个花瓶里有 f i f_i fi ( 1 ≤ f i ≤ 1 0 12 ) (1\leq f_i \leq 10^{12}) (1≤fi≤1012) 朵花。现在要选择 s s s ( 1 ≤ s ≤ 1 0 14 ) (1\leq s \leq 1…...
MySQL-----SELECT语句-查询
目录 SELECT语句-查询 1.格式 2.操作 3.算数表达式 SELECT语句-查询 1.格式 📖简单查询: 格式: select 字段1,字段n from 表名; 起别名: 通过在字段后添加 as 别名 as可以省略 改变表头 eg: select username "用户名",password as "…...
