【C++】- 类和对象(构造函数!!explicit关键字stastic关键字!!详解)

类和对象④

  • 构造函数初始化列表
  • explicit关键字
  • static成员

构造函数初始化列表

我们已经初步了解了构造函数------->类和对象②那么调用构造函数就是给了对象中各个成员变量一个合适的初始值。

但实际上,我们想要做的是初始化成员变量,在构造函数中对成员变量进行的赋值操作并不是对象的初始化,而只是给成员变量赋予了初始值。在构造函数体内部,可以多次对成员变量进行赋值操作,这与对象的初始化是不同的概念。

对象的初始化是指在创建对象时,为对象的成员变量分配内存空间并赋予初始值,这个过程只发生一次。而构造函数体内的赋值操作只是对已经存在的成员变量赋予新的值,这个过程可以在构造函数体内任意次数地进行。

举个例子来说明:

class MyClass {
public:
    int num;

    MyClass(int value) {
        num = value;  // 这是赋值操作,不是初始化
    }
};

MyClass obj(10);  // 创建对象,并调用构造函数

在上述例子中,构造函数MyClass(int value)中的num = value语句只是对成员变量num赋予了初始值,而不是对象的初始化。对象的初始化是在创建对象时,为成员变量num分配内存空间并赋予初始值,这个过程只发生一次。

在这里插入图片描述

需要注意的是,在C++11标准引入之前,我们无法在构造函数的初始化列表中直接对非静态成员变量进行初始化,只能在构造函数体内进行赋值操作。而在C++11以后,我们可以使用初始化列表来对成员变量进行初始化,这样更符合对象初始化的概念。

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟
一个放在括号中的初始值或表达式。

class MyClass {
public:
    int num;

    MyClass(int value) : num(value) {
        // 初始化列表中对成员变量进行初始化
    }
};

MyClass obj(10);  // 创建对象,并调用构造函数

在上述例子中,构造函数 MyClass(int value) 使用初始化列表对成员变量 num 进行了初始化,这是一种更优雅和高效的方式,它将赋值操作转化为了初始化操作。

还有需要注意的一点是,初始化列表的顺序应该与成员变量在类中声明的顺序一致,这样可以保证每个成员变量都能被正确地初始化。并且每个成员变量在初始化列表中只能出现一次

当类中包含以下成员时,必须放在初始化列表位置进行初始化:

  • 引用成员变量
  • const成员变量
  • 自定义类型成员(且该类没有默认构造函数时)

另外,成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后
次序无关

class A
{
public:
    A(int a)
       :_a1(a)
       ,_a2(_a1)
   {}
    
    void Print() {
        cout<<_a1<<" "<<_a2<<endl;
   }
private:
    int _a2;
    int _a1;
};
int main() {
    A aa(1);
    aa.Print();
}

在上面这段代码中,类A的构造函数使用了初始化列表来对成员变量进行初始化。构造函数中的Print函数用于打印成员变量的值。根据代码逻辑,在创建对象A aa(1)后,调用了Print函数进行输出。在Print函数中,会分别输出成员变量_a1和_a2的值。根据初始化列表的顺序,成员变量_a2在成员变量_a1之前进行初始化。因此,成员变量_a2的初始化使用了成员变量_a1的值。

因此,输出会是"1 1"。

explicit关键字

explicit是C++中的关键字,用于修饰类的单参数构造函数。它的作用是防止隐式类型转换,只允许显式地调用构造函数进行对象的创建。

在没有使用explicit关键字修饰的构造函数中,编译器会根据需要进行隐式类型转换。这可能导致一些意外的行为和错误的结果。使用explicit关键字可以避免这种隐式类型转换的发生。

下面是一个示例:

class MyClass {
public:
    explicit MyClass(int n) {
        // 构造函数体
    }
};

void func(MyClass obj) {
    // 函数体
}

int main() {
    MyClass obj1(10);  // 直接调用构造函数,显式地创建对象

    MyClass obj2 = 20;  // 错误!使用了隐式类型转换,编译错误

    func(30);  // 错误!使用了隐式类型转换,编译错误

    return 0;
}

在上述示例中,类MyClass的构造函数被explicit关键字修饰,它只能显式地被调用,不能进行隐式类型转换。

main函数中,obj1直接使用构造函数显式地创建对象,是合法的。但是,obj2func(30)都会导致编译错误,因为它们都尝试使用隐式类型转换调用构造函数。

使用explicit关键字可以避免一些潜在的错误,提高代码的可读性和安全性。

static成员

static成员是指在类中被声明为static的数据成员或函数成员。

static关键字用于将成员与类本身关联,而不是与类的每个实例对象关联。

对于static数据成员,它们被所有类的实例对象所共享,只有一个副本存在于内存中。它们可以用于在类的所有实例对象之间共享数据。static数据成员必须在类的定义体外进行初始化,并且不能在类的成员函数中直接访问非静态成员变量和成员函数。

对于static函数成员,它们属于类而不是对象,因此可以直接使用作用域解析运算符::来调用,不需要创建类的实例对象。static函数成员不能访问类的非静态成员变量和成员函数,只能访问类的静态成员变量和成员函数。

下面是一个示例:

#include <iostream>
using namespace std;

class MyClass {
public:
    static int count;  // 静态数据成员声明

    MyClass() {
        count++;  // 每次创建对象时增加count的值
    }

    static void PrintCount() {  // 静态函数成员声明
        cout << "Count: " << count << endl;
    }
};

int MyClass::count = 0;  // 静态数据成员定义和初始化

int main() {
    MyClass obj1;
    MyClass obj2;
    MyClass obj3;

    MyClass::PrintCount();  // 直接使用作用域解析运算符调用静态函数成员

    return 0;
}

在上述示例中,类MyClass定义了一个静态数据成员count和一个静态函数成员PrintCount。在main函数中,创建了三个MyClass类型的对象,每次创建对象时都会增加count的值。最终,通过MyClass::PrintCount()直接调用静态函数成员输出了count的值。

static成员可以用于在类的所有实例对象之间共享数据或方法,提高代码的效率和可维护性。但是,需要注意,在多线程编程中,对静态成员的并发访问可能会引发线程安全问题,需要进行适当的同步处理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新手学习指南:用Scala采集外卖平台

学习爬虫不是一蹴而就的&#xff0c;在掌握相关的知识点的同时&#xff0c;还要多加练习&#xff0c;学习是一部分&#xff0c;更多的还是需要自己上手操作&#xff0c;这里配合自己学习的基础&#xff0c;以及使用一些爬虫的专有库&#xff0c;就可以轻松达到自己想要的数据。…

Angular系列教程之自定义指令

文章目录 前言指令的基本概念在模板中使用指令总结 前言 在Angular中&#xff0c;指令是一种非常强大的工具&#xff0c;用于扩展HTML元素的功能和行为。它们允许我们创建可重用的组件&#xff0c;并在应用程序中的多个地方使用它们。本文将介绍Angular指令的基础知识&#xf…

【下云】旧笔记本实现私人服务器

背景&缘由&想法 背景&#xff1a; 自己是做Java的&#xff0c;做互联网或者说学计算机的都知道&#xff0c;近几年大环境太差&#xff0c;人却越来越多&#xff0c;造成行业越来越卷&#xff1b;针对Java来说&#xff0c;被迫要学习多方面的知识&#xff0c;工作拧螺…

压力测试+接口测试(工具jmeter)

jmeter是apache公司基于java开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简单。因 为jmeter是java开发的&#xff0c;所以运行的时候必须先要安装jdk才可以。jmeter是…

3.0.0 网络安全技术

一、端口安全 1、端口隔离 1.1 简介 以太交换网络中为了实现报文之间的二层隔离&#xff0c;用户通常将*不同的端口*加入*不同的VLAN*&#xff0c;实现二层广播域的隔离。只通过VLAN实现报文二层隔离&#xff0c;会浪费有限的VLAN资源&#xff0c;同时也只能实现基础的隔离操…

Python基础知识:整理17 -> 类和对象

1 初识对象 # 1. 设计一个类&#xff1a; 类的属性->成员变量、 类的行为->成员方法 class Student:name None # 记录学生姓名gender None # 记录学生性别age None # 记录学生年龄score None # 记录学生成绩def say(self): # 成员方法return (f"hel…

工业平板定制方案_基于联发科、紫光展锐平台的工业平板电脑方案

工业平板主板采用联发科MT6762平台方案&#xff0c;搭载Android 11.0操作系统&#xff0c; 主频最高2.0GHz&#xff0c;效能有大幅提升;采用12nm先进工艺&#xff0c;具有低功耗高性能的特点。 该工业平板主板搭载了IMG GE8320图形处理器&#xff0c;最高主频为680MHz, 支持108…

019、错误处理:不可恢复错误与panic!

鉴于上一篇文章过长&#xff0c;不方便大家阅读和理解&#xff0c;因此关于Rust中的错误处理&#xff0c; 我将分以下3篇来讲。 另外&#xff0c;随着我们学习的不断深入&#xff0c;难度也会越来越大&#xff0c;但不用担心。接下来只需要让自己的脚步慢一些&#xff0c;认真搞…

软件测试|教你如何使用Python绘制出奥运五环旗

简介 我们之前介绍过使用turtle来绘制正多边形&#xff0c;但是绘制正多边形只是turtle模块最基础的使用&#xff0c;我们可以使用turtle模块绘制出更多不一样的精彩图形&#xff0c;本文就来给大家介绍一个比较简单的turtle绘图实例&#xff0c;绘制奥运五环旗。 初始化参数…

JS | JS调用EXE

JS | JS调用EXE 网上洋洋洒洒一大堆文章提供,然我还是没找打合适的方案: 注册表方案做了如下测试(可行但是不推荐?): 先,键入文件名为 myprotocal.reg 的注册表,并键入一下信息: Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\openExe] //协议名…

[开发语言][c++]:Static关键字和全局变量

Static关键字和全局变量 1. 生命周期、作用域和初始化时机2. 全局变量3. Static 关键字3.1 面向过程3.1.1 静态全局变量3.1.2 静态局部变量&#xff08;单例中会使用&#xff09;3.1.3 静态函数 3.2 面向对象3.2.1 类内静态成员变量3.2.2 类内静态成员函数 Reference 写在前面&…

有n个水塔,初始每个水塔有a[i]的水,每个水塔一次最多拿b[i]的水,现从1~n依次在水塔中取水,没取完的水全部流入下一个水塔,求最终能取多少水

题目 思路&#xff1a; 假设有两个水塔1和2&#xff0c;分类讨论&#xff1a; 1、当a1 > b1时&#xff0c;2中剩下的水是a2 - b2 a1 - b1 2、当a1 < b1时&#xff0c;1中的水不会流到2中&#xff0c;2中剩下的水是a2 - b2 即最大&#xff08;a - b) 的后缀和 #incl…

【数字电子技术课程设计】多功能数字电子钟的设计

目录 摘要 1 设计任务要求 2 设计方案及论证 2.1 任务分析 2.1.1 晶体振荡器电路 2.1.2 分频器电路 2.1.3 时间计数器电路 2.1.4 译码驱动电路 2.1.5 校时电路 2.1.6 整点报时/闹钟电路 2.2 方案比较 2.3 系统结构设计 2.4 具体电路设计 3 电路仿真测试及结…

CMake tasks.json launch.json

hehedalinux:~/Linux/cmake/cmakeClass$ tree . ├── CMakeLists.txt ├── include │ ├── Gun.h │ └── Soldier.h ├── main.cpp └── src├── Gun.cpp└── Soldier.cpp2 directories, 6 files hehedalinux:~/Linux/cmake/cmakeClass$ launch.json&am…

linux主机的免密登录

实现linux主机之间的相互免密登录 在进行远程登录的时&#xff0c;服务器和主机间进行认证阶段分为&#xff1a; 基于口令认证&#xff08;不安全&#xff0c;易被抓包拦截获取&#xff09; 客户机连接服务器时&#xff0c;服务器将自己的公钥返回给客户机 客户机会将服务器的…

【报错】NVIDIA 驱动版本不兼容 — NVIDIA driver on your system is too old

【报错】NVIDIA 驱动版本不兼容 — NVIDIA driver on your system is too old 报错信息查看torch版本查看nvidia驱动版本 报错信息 CUDA initialization: The NVIDIA driver on your system is too old (found version 11040). Please update your GPU driver by downloading …

29 旋转工具箱

效果演示 实现了一个菜单按钮的动画效果&#xff0c;当鼠标悬停在菜单按钮上时&#xff0c;菜单按钮会旋转315度&#xff0c;菜单按钮旋转的同时&#xff0c;菜单按钮旋转的8个小圆圈也会依次旋转360度&#xff0c;并且每个小圆圈的旋转方向和菜单按钮的旋转方向相反&#xff0…

【SpringMVC】常用注解(续)

在SpringMVC常用注解一文中&#xff0c;已经对一些基本注解&#xff08;有Controller、RequestMapping、ResponseBody、RequestParam&#xff09;进行了简单介绍&#xff1b;在此篇文章中&#xff0c;将继续对剩余的几个常用注解进行简单介绍&#xff0c;有RequestBody、PathVa…

ElasticSearch入门篇

目录 一、 ElasticSearch的定位 二、 什么是倒排索引 三、 什么是全文检索 四、 ElasticSearch的数据存储原理 4.1 ElasticSearch与关系型数据库的数据结构对比 4.2 ElasticSearch的倒排索引原理 一、 ElasticSearch的定位 ElasticSearch是一款开源的分布式 搜索和…

力扣算法之滑动窗口题目--水果成篮

文章目录 题目解析不同之处解决办法解决图示 代码 题目解析 首先我们先看一下题目如下图所示 题目意思也比较容易理解其实就是你有一个篮子这个篮子只能装两个不同种类的水果&#xff0c;问你最多能装多少个水果&#xff0c;这里还贴心的弄了一个样列&#xff0c;121 可以看出…