当前位置: 首页 > news >正文

C++学习:类和对象(三)

一、深入讲解构造函数

1. 什么是构造函数?

构造函数(Constructor)是在创建对象时自动调用的特殊成员函数,用于初始化对象的成员变量。构造函数的名称与类名相同,没有返回类型

2. 构造函数的类型

(1)默认构造函数

没有参数或所有参数都有默认值的构造函数

class Person {
public:Person() {name = "Unknown";age = 0;}
private:std::string name;int age;
};
(2)有参构造函数

接受参数,用于自定义初始化对象的构造函数

class Person {
public:Person(const std::string& name, int age) : name(name), age(age) {}
private:std::string name;int age;
};
(3)拷贝构造函数

用于创建对象的副本

class Person {
public:Person(const Person& other) : name(other.name), age(other.age) {std::cout << "拷贝构造函数被调用" << std::endl;}
private:std::string name;int age;
};
(4)移动构造函数(C++11 引入)

用于移动资源,避免不必要的拷贝

class Person {
public:Person(Person&& other) noexcept : name(std::move(other.name)), age(other.age) {std::cout << "移动构造函数被调用" << std::endl;}
private:std::string name;int age;
};

3. 构造函数的初始化列表

使用初始化列表可以在构造函数中直接初始化成员,尤其是常量成员或引用类型的成员

class Person {
public:Person(const std::string& name, int age) : name(name), age(age) {}
private:const std::string name;int& age;
};

4. 构造函数的调用顺序

  • 基类构造函数先于派生类构造函数被调用
  • 成员对象的构造函数按照它们在类中声明的顺序被调用

5. 代码示例

#include <iostream>
#include <string>class Address {
public:Address(const std::string& city) : city(city) {std::cout << "Address 构造" << std::endl;}
private:std::string city;
};class Person {
public:Person() : name("Unknown"), age(0), address("Unknown City") {std::cout << "Person 默认构造" << std::endl;}Person(const std::string& name, int age, const std::string& city): name(name), age(age), address(city) {std::cout << "Person 有参构造" << std::endl;}Person(const Person& other): name(other.name), age(other.age), address(other.address) {std::cout << "Person 拷贝构造" << std::endl;}private:std::string name;int age;Address address;
};int main() {Person p1;Person p2("Alice", 30, "New York");Person p3 = p2;return 0;
}

二、深入理解封装

1. 什么是封装?

封装(Encapsulation)是将数据和操作数据的方法绑定在一起,保护对象的内部状态不被外部直接访问和修改。它是面向对象编程的基本特性之一

2. 访问控制符

  • public:公共成员,外部可以访问
  • protected:受保护成员,派生类可以访问
  • private:私有成员,只有类内部可以访问

3. 为什么需要封装?

  • 提高代码的安全性,防止数据被非法访问和修改
  • 隐藏内部实现细节,提供清晰的接口
  • 便于维护和扩展代码

4. 通过方法访问私有成员

class BankAccount {
public:BankAccount(double balance) : balance(balance) {}void deposit(double amount) {if (amount > 0) {balance += amount;}}bool withdraw(double amount) {if (amount > 0 && balance >= amount) {balance -= amount;return true;}return false;}double getBalance() const {return balance;}private:double balance;
};

5. 代码示例

#include <iostream>class Rectangle {
public:void setWidth(double w) {if (w > 0)width = w;}void setHeight(double h) {if (h > 0)height = h;}double getArea() const {return width * height;}private:double width;double height;
};int main() {Rectangle rect;rect.setWidth(10);rect.setHeight(5);std::cout << "面积:" << rect.getArea() << std::endl;return 0;
}

三、static 成员

1. 什么是 static 成员?

在类中,用 static 关键字修饰的成员称为静态成员。它们属于类本身,而不是某个对象

2. 静态成员变量

  • 所有对象共享同一份静态成员变量
  • 必须在类外进行定义和初始化
class Counter {
public:Counter() {++count;}static int getCount() {return count;}private:static int count;
};int Counter::count = 0;

3. 静态成员函数

  • 只能访问静态成员变量和其他静态成员函数
  • 可以在不创建对象的情况下调用
class Math {
public:static double pi() {return 3.14159;}
};

4. 代码示例

#include <iostream>class Student {
public:Student(const std::string& name) : name(name) {++totalStudents;}~Student() {--totalStudents;}static int getTotalStudents() {return totalStudents;}private:std::string name;static int totalStudents;
};int Student::totalStudents = 0;int main() {std::cout << "当前学生人数:" << Student::getTotalStudents() << std::endl;Student s1("Alice");Student s2("Bob");std::cout << "当前学生人数:" << Student::getTotalStudents() << std::endl;{Student s3("Charlie");std::cout << "当前学生人数:" << Student::getTotalStudents() << std::endl;}std::cout << "当前学生人数:" << Student::getTotalStudents() << std::endl;return 0;
}

四、友元(friend

1. 什么是友元?

友元是被类授予访问其私有和保护成员权限的函数或类。使用 friend 关键字声明

2. 友元函数

  • 可以是普通函数或者类的成员函数
  • 在类内声明,在类外定义
class Box {
private:double width;public:friend void setWidth(Box& b, double w);
};void setWidth(Box& b, double w) {b.width = w;
}

3. 友元类

  • 一个类可以将另一个类声明为友元,从而该友元类的成员函数可以访问本类的私有和保护成员
class Engine;class Car {
private:int speed;friend class Engine;
};class Engine {
public:void setSpeed(Car& car, int s) {car.speed = s;}
};

4. 友元的用途

  • 当需要某个函数或类访问另一个类的私有成员时
  • 应谨慎使用,避免破坏封装性

5. 代码示例

#include <iostream>class Secret {
private:std::string password;public:Secret(const std::string& pwd) : password(pwd) {}friend void reveal(const Secret& s);
};void reveal(const Secret& s) {std::cout << "秘密是:" << s.password << std::endl;
}int main() {Secret s("123456");reveal(s);return 0;
}

五、内部类(嵌套类)

1. 什么是内部类?

在一个类的定义中定义另一个类,称为内部类或嵌套类

2. 内部类的特性

  • 内部类可以访问外部类的私有和保护成员
  • 外部类需要通过对象来访问内部类的成员

3. 什么时候使用内部类?

  • 当某个类只为另一个类服务时
  • 为了更好地组织代码,提升封装性

4. 代码示例

#include <iostream>class Outer {
private:int outerData;public:Outer(int data) : outerData(data) {}class Inner {public:void displayOuterData(const Outer& o) {std::cout << "外部类数据:" << o.outerData << std::endl;}};
};int main() {Outer o(100);Outer::Inner i;i.displayOuterData(o);return 0;
}

六、匿名对象

1. 什么是匿名对象?

没有被命名的临时对象,通常在表达式中创建,使用完后立即销毁

2. 匿名对象的用途

  • 作为函数的返回值或参数
  • 进行临时运算

3. 代码示例

#include <iostream>class Number {
public:Number(int value) : value(value) {std::cout << "构造:" << value << std::endl;}~Number() {std::cout << "析构:" << value << std::endl;}int getValue() const {return value;}private:int value;
};Number createNumber(int x) {return Number(x);
}int main() {Number(10); // 创建匿名对象std::cout << "--------" << std::endl;Number n = createNumber(20);std::cout << "n 的值:" << n.getValue() << std::endl;return 0;
}

七、拷贝对象时的一些编译器优化

1. 什么是拷贝消除?

编译器优化的一种,避免不必要的对象拷贝,提高性能

2. 返回值优化(RVO)

当函数返回对象时,直接在调用者的空间构造对象,避免临时对象的生成

class Data {
public:Data() {std::cout << "Data 构造" << std::endl;}Data(const Data&) {std::cout << "Data 拷贝构造" << std::endl;}~Data() {std::cout << "Data 析构" << std::endl;}
};Data getData() {Data d;return d;
}int main() {Data d = getData();return 0;
}

3. 使用 std::move 和移动语义

  • 在需要移动对象而非拷贝时,使用 std::move
#include <vector>
#include <string>int main() {std::vector<std::string> vec;std::string str = "Hello";vec.push_back(std::move(str)); // 移动 str,而不是拷贝return 0;
}

4. 代码示例

#include <iostream>class Example {
public:Example() {std::cout << "构造函数" << std::endl;}Example(const Example&) {std::cout << "拷贝构造函数" << std::endl;}Example(Example&&) noexcept {std::cout << "移动构造函数" << std::endl;}~Example() {std::cout << "析构函数" << std::endl;}
};Example createExample() {Example e;return e;
}int main() {Example e = createExample();return 0;
}

相关文章:

C++学习:类和对象(三)

一、深入讲解构造函数 1. 什么是构造函数&#xff1f; 构造函数&#xff08;Constructor&#xff09;是在创建对象时自动调用的特殊成员函数&#xff0c;用于初始化对象的成员变量。构造函数的名称与类名相同&#xff0c;没有返回类型 2. 构造函数的类型 &#xff08;1&…...

高阶数据结构--图(graph)

图&#xff08;graph&#xff09; 1.并查集1. 并查集原理2. 并查集实现3. 并查集应用 2.图的基本概念3. 图的存储结构3.1 邻接矩阵3.2 邻接矩阵的代码实现3.3 邻接表3.4 邻接表的代码实现 4. 图的遍历4.1 图的广度优先遍历4.2 广度优先遍历的代码 1.并查集 1. 并查集原理 在一…...

xxl-job java.sql.SQLException: interrupt问题排查

近期生产环境固定凌晨报错&#xff0c;提示 ConnectionManager [Thread-23069] getWriteConnection db:***,pattern: error, jdbcUrl: jdbc:mysql://***:3306/***?connectTimeout3000&socketTimeout180000&autoReconnecttrue&zeroDateTimeBehaviorCONVERT_TO_NUL…...

jmeter压测工具环境搭建(Linux、Mac)

目录 java环境安装 1、anaconda安装java环境&#xff08;推荐&#xff09; 2、直接在本地环境安装java环境 yum方式安装jdk 二进制方式安装jdk jmeter环境安装 1、jmeter单机安装 启动jmeter 配置环境变量 jmeter配置中文 2、jmeter集群搭建 多台机器部署jmeter集群…...

docker设置加速

sudo tee /etc/docker/daemon.json <<-‘EOF’ { “registry-mirrors”: [ “https://register.liberx.info”, “https://dockerpull.com”, “https://docker.anyhub.us.kg”, “https://dockerhub.jobcher.com”, “https://dockerhub.icu”, “https://docker.awsl95…...

使用requestAnimationFrame写防抖和节流

debounce.ts 防抖工具函数: function Animate() {this.timer null; }Animate.prototype.start function (fn) {if (!fn) {throw new Error(需要执行函数);}if (this.timer) {this.stop();}this.timer requestAnimationFrame(fn); }Animate.prototype.stop function () {i…...

Puppeteer 与浏览器版本兼容性:自动化测试的最佳实践

Puppeteer 支持的浏览器版本映射&#xff1a;从 v20.0.0 到 v23.6.0 自 Puppeteer v20.0.0 起&#xff0c;这个强大的自动化库开始支持与 Chrome 浏览器的无头模式和有头模式共享相同代码路径&#xff0c;为自动化测试带来了更多便利。从 v23.0.0 开始&#xff0c;Puppeteer 进…...

Java方法重写

在Java中&#xff0c;方法重写是指在子类中重新定义父类中已经定义的方法。以下是Java方法重写的基本原则&#xff1a; 子类中的重写方法必须具有相同的方法签名&#xff08;即相同的方法名、参数类型和返回类型&#xff09;。子类中的重写方法不能比父类中的原方法具有更低的…...

vscode通过.vscode/launch.json 内置php服务启动thinkphp 应用后无法加载路由解决方法

我们在使用vscode的 .vscode/launch.json Launch built-in server and debug 启动thinkphp应用后默认是未加载thinkphp的路由文件的&#xff0c; 这个就导致了&#xff0c;某些thinkphp的一些url路由无法访问的情况&#xff0c; 如http://0.0.0.0:8000/api/auth.admin/info这…...

Webserver(2.6)有名管道

目录 有名管道有名管道使用有名管道的注意事项读写特性有名管道实现简单版聊天功能拓展&#xff1a;如何解决聊天过程的阻塞 有名管道 可以用在没有关系的进程之间&#xff0c;进行通信 有名管道使用 通过命令创建有名管道 mkfifo 名字 通过函数创建有名管道 int mkfifo …...

四足机器人实战篇之一:波士顿spot机器人工程实现分析

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、机器人发展历史二、硬件系统及电机执行器篇硬件系统电机执行器传感器机处理器电气连接三、感知(视觉点云、局部地图、定位)篇1.深度相机获取…...

TensorFlow 预训练目标检测模型集合

Tensorflow 提供了一系列在不同数据集上预训练的目标检测模型&#xff0c;包括 COCO 数据集、Kitti 数据集、Open Images 数据集、AVA v2.1 数据集、iNaturalist 物种检测数据集 和 Snapshot Serengeti 数据集。这些模型可以直接用于推理&#xff0c;特别是当你对这些数据集中已…...

字符串的区别

C 和 Java 字符串的区别 最近 C 和 Java 在同步学习&#xff0c;都有个字符串类型&#xff0c;但二者不太一样&#xff0c;于是就做了些许研究。 在编程中&#xff0c;字符串作为数据类型广泛应用于不同的场景。虽然 C 和 Java 都允许我们处理字符串&#xff0c;但它们在字符…...

EMR Serverless Spark:一站式全托管湖仓分析利器

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 李钰&#xff08;绝顶&#xff09; | 阿里云智能集团资深技术专家&#xff0c;阿里云 EMR 团队负责人 活动&#xff1a; 2024 云栖大会 AI - 开源大数据专场 数据平台技术演变 …...

Linux find 匹配文件内容

在Linux中&#xff0c;你可以使用find命令结合-exec或者-execgrep来查找匹配特定内容的文件。以下是一些示例&#xff1a; 查找当前目录及其子目录下所有文件内容中包含"exampleText"的文件&#xff1a; find . -type f -exec grep -l "exampleText" {} \…...

【Redis优化——如何优雅的设计key,优化BigKey,Pipeline批处理Key】

Redis优化——如何优雅的设计key&#xff0c;优化BigKey&#xff0c;Pipeline批处理Key 一、Key的设计1. 命名规范2. 长度限制在44字节以内 二、BigKey优化1. 查找bigkey2. 删除BigKey3. 优化BigKey 三、Pipeline批处理Key1. 单节点的Pipeline2. 集群下的Pipeline 一、Key的设计…...

数据结构与算法分析:你真的理解图算法吗——深度优先搜索(代码详解+万字长文)

一、前言 图是计算机科学中用来表示复杂结构信息的一种基本结构。本章我们会讨论一些通用的围表示法,以及一些频繁使用的图算法。本质上来说,一个图包含一个元素集合(也就是顶点),以及元素两两之间的关系(也就是边),由于应用范围所限,本章我们仅仅讨论简单图,简单围并不会如(a…...

LinkedList 分析

LinkedList 简介 LinkedList 是一个基于双向链表实现的集合类&#xff0c;经常被拿来和 ArrayList 做比较。关于 LinkedList 和ArrayList的详细对比&#xff0c;我们 Java 集合常见面试题总结(上)有详细介绍到。 双向链表 不过&#xff0c;我们在项目中一般是不会使用到 Link…...

【C/C++】模拟实现strlen

学习目标&#xff1a; 使用代码模拟实现strlen。 逻辑&#xff1a; strlen 需要输入一个字符串数组类型的变量&#xff0c;并且返回一个整型类型的数据。strlen 需要计算字符串数组有多少个元素。 代码1&#xff1a;使用计数器 #define _CRT_SECURE_NO_WARNINGS 1 #include&…...

mybatis从浅入深一步步演变分析

mybatis从浅入深一步步演变分析 版本一&#xff1a;不使用代理&#xff08;非spring&#xff09; package com.yimeng.domain;public class User {private int id;private String username;private String password;public int getId() {return id;}public void setId(int id…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

uni-app学习笔记二十七--设置底部菜单TabBar的样式

官方文档地址&#xff1a;uni.setTabBarItem(OBJECT) | uni-app官网 uni.setTabBarItem(OBJECT) 动态设置 tabBar 某一项的内容&#xff0c;通常写在项目的App.vue的onLaunch方法中&#xff0c;用于项目启动时立即执行 重要参数&#xff1a; indexnumber是tabBar 的哪一项&…...

实现p2p的webrtc-srs版本

1. 基本知识 1.1 webrtc 一、WebRTC的本质&#xff1a;实时通信的“网络协议栈”类比 将WebRTC类比为Linux网络协议栈极具洞察力&#xff0c;二者在架构设计和功能定位上高度相似&#xff1a; 分层协议栈架构 Linux网络协议栈&#xff1a;从底层物理层到应用层&#xff08;如…...

边缘计算设备全解析:边缘盒子在各大行业的落地应用场景

随着工业物联网、AI、5G的发展&#xff0c;数据量呈爆炸式增长。但你有没有想过&#xff0c;我们生成的数据&#xff0c;真的都要发回云端处理吗&#xff1f;其实不一定。特别是在一些对响应时间、网络带宽、数据隐私要求高的行业里&#xff0c;边缘计算开始“火”了起来&#…...

Three.js + Vue3 加载GLB模型项目代码详解

本说明结合 src/App.vue 代码,详细解释如何在 Vue3 项目中用 three.js 加载并显示 glb 模型。 1. 依赖与插件导入 import {onMounted, onUnmounted } from vue import * as THREE from three import Stats from stats.js import {OrbitControls } from three/examples/jsm/co…...