深入探究C++四大关键特性:初始化列表、友元函数、内部类与static成员

目录

1. 构造函数不为人知的那些事

1.1 构造函数体赋值与初始化列表对比

1.2 explicit关键字与构造函数隐式转换

2. static成员

2.1 static成员的概念

2.2 static成员的特性与应用

2.3 小结

3. C++11 成员变量初始化新用法

4. 友元

4.1 友元函数

4.2 友元类

5. 内部类

5.1 内部类的概念及特性

前言: 在C++编程世界中,精深的语言特性和编码技巧对于编写出高效、可靠且易于维护的代码至关重要。本文将深度剖析C++中的五大关键特性:构造函数的秘密static成员C++11成员变量初始化新特性友元函数与友元类,以及内部类的概念及其特性,并辅以丰富的代码示例和详尽的注解,力求帮助读者全方位理解并运用这些特性。

1. 构造函数不为人知的那些事

1.1 构造函数体赋值与初始化列表对比

在C++中,构造函数不仅可以通过其函数体给成员变量赋值,还可利用初始化列表进行初始化。二者的主要差异在于初始化列表会在构造函数体执行前优先完成初始化动作,尤其适用于引用、const成员以及无默认构造函数的自定义类型成员。

// 构造函数体赋值
class ExampleClass {
public:int value;ExampleClass(int val) {// 赋值操作发生在构造函数体内value = val; // 首先执行默认初始化,然后赋值}
};// 使用初始化列表
class ImprovedClass {
public:int value;ImprovedClass(int val) : value(val) { // 利用初始化列表直接初始化成员变量// 注意:此处value已经初始化完毕,无需额外赋值操作}
};
1.2 explicit关键字与构造函数隐式转换

在单参数构造函数前添加explicit关键字,可以阻止编译器进行隐式类型转换构造,有利于消除潜在的二义性并提高代码清晰度。

class MyIntWrapper {
public:explicit MyIntWrapper(int v) : value(v) {} // 显示标记为显式构造函数
private:int value;
};void process(MyIntWrapper obj) {}int main() {int x = 10;// 下面的语句将编译失败,因为MyIntWrapper构造函数是显式的// process(x); // 错误:不允许隐式转换构造// 正确的做法:process(MyIntWrapper(x)); // 显式转换调用构造函数
}

2. static成员

2.1 static成员的概念

static成员变量和函数是与类绑定而非与类的实例关联的全局资源。它们在整个程序生命周期内只有一份拷贝,并可通过类名或作用域解析运算符(::)进行访问。

2.2 static成员的特性与应用

- static成员变量在整个程序中共享,且可在类外部初始化。
- static成员函数不含有`this`指针,因此不能访问非static成员,通常用于处理与类状态相关的全局功能。

class Counter {
public:static int count;Counter() { ++count; } // 每实例化一个对象,计数增加~Counter() { --count; } // 对象销毁时,计数减小static void displayCount() { // static成员函数展示当前对象数量std::cout << "Total objects created: " << count << std::endl;}private:static int count; // 声明静态成员变量
};
// 在类外初始化静态成员变量
int Counter::count = 0;int main() {Counter c1;Counter c2;Counter::displayCount(); // 直接通过类名调用静态成员函数
}
2.3 小结

static成员适用于存储跨对象共享的数据,以及提供与类状态紧密相关的全局功能,但需要注意线程安全问题。

3. C++11 成员变量初始化新用法

C++11引入了类内部成员变量的初始化新语法,允许在声明处直接给出默认值,虽非构造函数初始化列表的一部分,但简化了成员变量初始化的过程。

1class ModernClass {
2public:
3    int value {5}; // C++11 引入的成员变量初始化方式,默认值为5
4};

4. 友元

4.1 友元函数

友元函数是不受类访问限制的非成员函数,能够直接访问类的私有和保护成员。友元关系的建立增强了代码间的交互能力,但应谨慎使用以保持类的封装性。

class Circle {double radius;friend void printRadius(const Circle& c); // 声明printRadius为友元函数
public:Circle(double r) : radius(r) {}
};void printRadius(const Circle& c) {std::cout << "Circle's radius is: " << c.radius << std::endl; // 直接访问私有成员
}int main() {Circle circle(10);printRadius(circle); // 友元函数正常调用
}
4.2 友元类

友元类允许一个类的所有成员函数可以访问另一个类的私有和保护成员,增强了类间通信和协作的能力。

class A;
class B {friend class A; // B声明A为友元类
private:int b_value;
};class A {
public:void accessB(B& b_instance) {std::cout << "B's private member: " << b_instance.b_value << std::endl;}
};int main() {B b_obj;b_obj.b_value = 42; // 只有B的成员函数或友元类A能访问b_valueA a_obj;a_obj.accessB(b_obj); // 类A可以通过友元关系访问B的私有成员
}

5. 内部类

5.1 内部类的概念及特性

内部类是在另一个类定义内部定义的类,它能够直接访问外部类的所有成员,包括私有和保护成员。内部类可以强化类的封装性,实现逻辑模块化,降低耦合度。

class Outer {
public:class Inner {public:void accessOuter(Outer& outer) {std::cout << "Outer's private member: " << outer.privateValue << std::endl;}};private:int privateValue {10};
};int main() {Outer outer;Outer::Inner inner;inner.accessOuter(outer); // 内部类可以访问外部类的私有成员
}

总结: 通过深入探讨C++构造函数的各种微妙之处、static成员的使用场景和规则、C++11中成员变量初始化的创新方法,以及友元函数和友元类的应用和内部类的概念,我们得以窥见C++语言强大而灵活的一面。熟练掌握这些特性将极大地提升我们的编程技能,让我们能够编写出更加优雅、高效且安全的C++代码。同时,务必谨记适度使用这些特性,避免过度破环类的封装性和代码的可维护性。

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

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

相关文章

Python 中的花卉矩阵组合

使用场景描述 (rib) 协议编写脚本的基础知识。通过创建在 3D 空间中转换的基本几何图形,解决了 xyz 坐标系的基础知识。初步渲染是使用基本着色完成的,因此可以更容易地看到几何体。RenderMan 图1 图 1 是我作为作业参考的示例图片,并尝试匹配 中的图片。为了完成这项任务…

Python | Leetcode Python题解之第61题旋转链表

题目&#xff1a; 题解&#xff1a; class Solution:def rotateRight(self, head: ListNode, k: int) -> ListNode:if k 0 or not head or not head.next:return headn 1cur headwhile cur.next:cur cur.nextn 1if (add : n - k % n) n:return headcur.next headwhi…

机器学习的两种典型任务

机器学习中的典型任务类型可以分为分类任务&#xff08;Classification&#xff09;和回归任务&#xff08;Regression&#xff09; 分类任务 回归任务 简单的理解&#xff0c;分类任务是对离散值进行预测&#xff0c;根据每个样本的值/特征预测该样本属于类 型A、类型B 还是类…

Django后台项目开发实战四

用户可以浏览工作列表以及工作详情 第四阶段 在 jobs 文件夹下创建 templates 文件夹&#xff0c;在里面创建 base.html 网页&#xff0c;内容如下 <!-- base.html --> <div style"text-align:center;"><h1 style "margin:auto; width:50%;&…

MATLAB - 自定义惯性矩阵

系列文章目录 前言 一、关键惯性约定 Simscape 多体软件在惯性定义中采用了一系列约定。请注意这些约定&#xff0c;因为如果手动进行惯性计算&#xff0c;这些约定可能会影响计算结果。如果您的惯性数据来自 CAD 应用程序或其他第三方软件&#xff0c;这些约定还可能影响到您需…

Mac好用又好看的终端iTerm2 + oh-my-zsh

Mac好用又好看的终端iTerm2 1. iTerm2的下载安装2. oh-my-zsh的安装2.1 官网安装方式2.2 国内镜像源安装方式 3. oh-my-zsh配置3.1 存放主题的路径3.2 存放插件的路径3.3 配置文件路径 1. iTerm2的下载安装 官网下载&#xff1a; iTerm2 2. oh-my-zsh的安装 oh-my-zsh是一…

C语言 | Leetcode C语言题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; char* getPermutation(int n, int k) {int factorial[n];factorial[0] 1;for (int i 1; i < n; i) {factorial[i] factorial[i - 1] * i;}--k;char* ans malloc(n 1);ans[n] \0;int valid[n 1];for (int i 0; i < n; i) {val…

飞书API(6):使用 pandas 处理数据并写入 MySQL 数据库

一、引入 上一篇了解了飞书 28 种数据类型通过接口读取到的数据结构&#xff0c;本文开始探讨如何将这些数据写入 MySQL 数据库。这个工作流的起点是从 API 获取到的一个完整的数据&#xff0c;终点是写入 MySQL 数据表&#xff0c;表结构和维格表结构类似。在过程中可以有不同…

【Leetcode每日一题】 动态规划 - 简单多状态 dp 问题 - 按摩师(难度⭐)(64)

1. 题目解析 题目链接&#xff1a;面试题 17.16. 按摩师 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 一、状态定义 在解决这类动态规划问题时&#xff0c;首先我们需要明确状态的定义。对于本题&#xff0c;我们…

在mac上安装node.js及使用npm,yarn相关命令教程

1、安装node.js 官网&#xff1a;Node.js — Download Node.js 选择需要的版本&#xff0c;点击DownLoad 2、点击继续&#xff0c;直到安装成功。 2.1打开终端输入命令node -v 显示版本号则说明已安装成功 3、全局安装yarn命令 1、sudo npm install --global yarn &#xf…

Git学习笔记(五)IDEA使用Git

在前面几篇文章中&#xff0c;我们已经介绍了git的基础知识&#xff0c;知道了其主要作用是用来进行代码的版本管理&#xff1b;并且已经介绍了Git操作的常用命令。在日常的开发环境下&#xff0c;除了通过Bash命令行来操作Git之外&#xff0c;我们另外一种常用的操作方式则是直…

基于STC12C5A60S2系列1T 8051单片机的Proteus中的单片机发送一帧或一串数据给串口调试助手软件接收区显示出来的串口通信应用

基于STC12C5A60S2系列1T 8051单片机的Proteus中的单片机发送一帧或一串数据给串口调试助手软件接收区显示出来的串口通信应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机串口通信介绍STC12C5A60S2系列1T 8051单片机串口通信的结构基于STC12C5A60S2系列…

Python_GUI框架 PyQt 与 Pyside6的介绍

Python_GUI框架 PyQt 与 Pyside6的介绍 一、简介 在Python的GUI&#xff08;图形用户界面&#xff09;开发领域&#xff0c;PyQt和PySide6是两个非常重要的工具包。它们都基于Qt库&#xff0c;为Python开发者提供了丰富的GUI组件和强大的功能。当然Python也有一些其他的GUI工…

手把手教数据结构与算法:优先级队列(银行排队问题)

队列 基本概念 队列的定义 队列&#xff08;Queue&#xff09;&#xff1a;队列是一种常见的数据结构&#xff0c;遵循先进先出&#xff08;First-In-First-Out, FIFO&#xff09;的原则。在队列中&#xff0c;元素按照进入队列的顺序排列。队列是一个线性的数据结构&#x…

【团体程序设计天梯赛】往年关键真题 L2-036 网红点打卡攻略 模拟 L2-037 包装机 栈和队列 详细分析完整AC代码

【团体程序设计天梯赛 往年关键真题 详细分析&完整AC代码】搞懂了赛场上拿下就稳 【团体程序设计天梯赛 往年关键真题 25分题合集 详细分析&完整AC代码】&#xff08;L2-001 - L2-024&#xff09;搞懂了赛场上拿下就稳了 【团体程序设计天梯赛 往年关键真题 25分题合…

《Redis使用手册之列表》

《Redis使用手册之列表》 目录 **《Redis使用手册之列表》****LPUSH&#xff1a;将元素推入列表左端****LPUSHX、RPUSHX&#xff1a;只对已存在的列表执行推入操作****LPOP&#xff1a;弹出列表最左端的元素****RPOP&#xff1a;弹出列表最右端的元素****RPOPLPUSH&#xff1a;…

ElasticSearch教程入门到精通——第二部分(基于ELK技术栈elasticsearch 7.x新特性)

ElasticSearch教程入门到精通——第二部分&#xff08;基于ELK技术栈elasticsearch 7.x新特性&#xff09; 1. JavaAPI-环境准备1.1 新建Maven工程——添加依赖1.2 HelloElasticsearch 2. 索引2.1 索引——创建2.2 索引——查询2.3 索引——删除 3. 文档3.1 文档——重构3.2 文…

SQL 基础 | BETWEEN 的常见用法

在SQL中&#xff0c;BETWEEN是一个操作符&#xff0c;用于选取介于两个值之间的数据。 它包含这两个边界值。BETWEEN操作符常用于WHERE子句中&#xff0c;以便选取某个范围内的值。 以下是BETWEEN的一些常见用法&#xff1a; 选取介于两个值之间的值&#xff1a; 使用 BETWEEN来…

基于昇腾AI | 英码科技EA500I使用AscendCL实现垃圾分类和视频物体分类应用

现如今&#xff0c;人工智能迅猛发展&#xff0c;AI赋能产业发展的速度正在加快&#xff0c;“AI”的需求蜂拥而来&#xff0c;但AI应用快速落地的过程中仍存在很大的挑战&#xff1a;向下需要适配的硬件&#xff0c;向上需要完善的技术支持&#xff0c;两者缺一不可。 基于此&…

【配置】Docker搭建JSON在线解析网站

云服务器打开端口8787 连接上docker运行 docker run -id --name jsonhero -p 8787:8787 -e SESSION_SECRETabc123 henryclw/jsonhero-webhttp://ip:8787访问 Github&#xff1a;地址