【C++】类与对象(四)——初始化列表|explicit关键字|static成员|友元|匿名对象

在这里插入图片描述

前言:
初始化列表,explicit关键字,static成员,友元,匿名对象


文章目录

  • 一、构造函数的初始化列表
    • 1.1 构造函数体内赋值
    • 1.2 初始化列表
  • 二、explicit关键字
  • 三、static成员
  • 四、友元
    • 4.1 友元函数
    • 4.2 友元类
  • 五、内部类
  • 六、匿名对象

一、构造函数的初始化列表

1.1 构造函数体内赋值

class Date{
public:
	Date(int year, int month, int day){
		//赋值,并非初始化
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

构造函数调用之后,在函数体中给成员变量赋值,但这并不能称为初始化,因为初始化是在变量或对象的创建时进行的,如果有初始化,那么仅有一次只有一次,而构造函数体内可以多次赋值。

对于某些类型的成员变量,必须进行初始化。函数体内并不能满足这些类型的成员变量进行初始化,因此有了初始化列表的概念。


1.2 初始化列表

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

_year _month _day被year,month,day进行初始化

Date(int year, int month, int day) :
		_year(year), 
		_month(month), 
		_day(day) {
		//函数体内其他操作
}	
  1. 实际上,即使没有显式写出初始化列表,成员变量依然会走初始化列表,但是因为没有初始值,因此成员变量是默认值。且初始化列表的顺序是成员变量声明的顺序。
    在这里插入图片描述

  2. 以下成员,必须放在初始化列表位置进行初始化

    • 引用成员变量
    • const成员变量
    • 自定义类型成员(且该类没有默认构造函数时)
    class A{
    public:
    	A(int a):_a(a){
    
    	}
    private:
    	int _a;
    };
    
    class B{
    private:
    	A _aobj;      // 自定义类型且没有默认构造函数
    	int& _ref;    // 引用
    	const int _n; // const 
    public:
    	// _aobj(a)可以理解为调用A类的构造函数
    	B(int a, int ref):_aobj(a), _ref(ref), _n(0){
    		// 其他操作
    	}
    };
    
    int main() {               
    	B b(10,5);
    	return 0;
    }
    
  3. 成员变量声明时提供缺值
    当成员变量没有在初始化列表初始化时,成员变量被默认初始化为缺省值。

    class Date{
    public:
    	Date(int year, int month, int day) :
    		_month(month),
    		_day(day) {
    		//函数体内其他操作
    	}
    private:
    	int _year = 1;
    	int _month;
    	int _day;
    };
    
    int main() {
    	//B b();
    	Date d(2024, 1, 31);
    	return 0;
    }
    

    在这里插入图片描述

通常初始化列表与构造函数体内赋值混合使用。


二、explicit关键字

  1. 单参数构造函数可以支持隐式类型的转换。
    意思是允许通过给定类型的单一参数将对象从一种类型转换为另一种类型,而无需显式调用构造函数。

    class Distance {
    private:
        double meters;
    
    public:
        // 单参数构造函数,允许从 double 类型隐式转换为 Distance 类型
        Distance(double m) : meters(m) {}  
    };
    
    int main() {
        // 隐式类型转换:double 到 Distance
        Distance d1 = 10.5;
    
        // 显式类型转换也是可行的
        Distance d2 = Distance(15.2);
        return 0;
    }
    

    在这个例子中,Distance 类具有一个单参数构造函数,允许将 double 类型的值隐式转换为 Distance 类型。当我们使用 Distance d1 = 10.5; 时,编译器会自动调用单参数构造函数,将 10.5 隐式转换为 Distance 类型的对象 d1

  2. C++11及之后的标准中,引入了一种新的特性,即“允许多参数的构造函数用于隐式类型转换”

    例如:

    class MyClass {
    public:
        // 多参数的构造函数
        MyClass(int x, double y) {
            // 构造函数逻辑
            std::cout << "Constructing MyClass with parameters: " << x << ", " << y << std::endl;
        }
    };
    
    int main() {
        // 隐式类型转换,调用构造函数
        MyClass obj = {42, 3.14};
    
        return 0;
    }
    

    在这个例子中,MyClass 类具有一个接受两个参数的构造函数。使用初始化列表 {42, 3.14} 进行对象的初始化时,实际上发生了隐式类型转换,将两个参数传递给构造函数。

  3. 当一个构造函数被 explicit 修饰时,它禁止隐式类型转换,只允许显式调用。

    explicit Distance(double m) : meters(m) {}
    
    // 隐式类型转换会引发编译错误
    Distance d1 = 10.5;  // 错误
    
    // 必须使用显式类型转换
    Distance d2 = Distance(15.2);  // 正确
    

三、static成员

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用
static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化

  1. 静态数据成员: 静态数据成员是属于类而不是类的对象的成员变量。所有类的对象共享相同的静态数据成员。

    class MyClass {
    public:
        // 构造函数,用于增加 count
        MyClass() {
            count++;
        }
        int& GetCount() {
            return count;
        }
    private:
        // 静态数据成员
        static int count;
    };
    
    // 初始化静态数据成员
    int MyClass::count = 0;
    
    int main() {
        // 创建对象,增加 count
        MyClass obj1;
        MyClass obj2;
    
        // 访问静态数据成员
        std::cout << "Count: " << obj1.GetCount() << std::endl;
        std::cout << "Count: " << obj2.GetCount() << std::endl;
    
        return 0;
    }
    
  2. 静态成员函数: 静态成员函数是不依赖于类的实例而存在的函数。它没有访问类的非静态成员,因为它不通过实例来调用,而是通过类名和范围解析运算符 :: 来调用。

    class MathOperations {
    public:
        // 静态成员函数,用于加法运算
        static int add(int a, int b) {
            return a + b;
        }
    };
    
    int main() {
        // 调用静态成员函数
        int result = MathOperations::add(3, 5);
        std::cout << "Result: " << result << std::endl;
    
        return 0;
    }
    

特性总结

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受publicprotectedprivate 访问限定符的限制

静态成员函数可以调用非静态成员函数吗?
非静态成员函数可以调用类的静态成员函数吗?

静态成员函数可以调用非静态成员函数,但非静态成员函数不能直接调用类的静态成员函数。这是因为静态成员函数在调用时没有实例上下文,而非静态成员函数必须通过实例来调用。


四、友元

友元(Friend)可以用来解决类的封装性和访问控制方面的一些限制。友元可以是函数、类或者整个类中的函数。友元的存在允许特定的外部实体访问类的私有或受保护成员。

4.1 友元函数

友元函数:使用 friend 关键字声明一个非成员函数,允许该非成员函数访问该类的私有成员。

下面是一个简单的示例:
友元函数的声明通常放在类的声明中,友元函数的定义放在类的外部。

class MyClass {
private:
    int privateData;

public:
    MyClass(int data) : privateData(data) {}

    // 声明友元函数
    friend void displayPrivateData(const MyClass&);
};

// 定义友元函数
void displayPrivateData(const MyClass& obj) {
    std::cout << "Private data: " << obj.privateData << std::endl;
}

int main() {
    MyClass obj(42);
    displayPrivateData(obj); // 友元函数可以访问私有成员
    return 0;
}

displayPrivateData 函数被声明为 MyClass 的友元函数,因此它可以访问 MyClass 中的私有成员 privateData。在 main 函数中,我们可以直接调用 displayPrivateData 函数来显示 obj 对象的私有成员数据。

需要注意的是,友元函数不是类的成员函数,因此它们不能使用成员访问运算符 .-> 来访问私有成员,而是需要通过参数传递对象来访问。


4.2 友元类

友元类:将一个类将另一个类声明为友元,从而允许友元类访问该类的私有成员和受保护成员。

举例:

class MyClass {
private:
    int privateMember;

    // 将 FriendClass 声明为友元类
    friend class FriendClass;

public:
    MyClass(int data) : privateMember(data) {}
};

class FriendClass {
public:
    void accessPrivateMember(const MyClass& obj) {
        // 友元类可以访问 MyClass 的私有成员
        int data = obj.privateMember;
    }
};

int main() {
    MyClass a(10);
    FriendClass b;
    b.accessPrivateMember(a);
    return 0;
}

在这个例子中,FriendClass 被声明为 MyClass 的友元类。因此,FriendClass 的成员函数 accessPrivateMember 可以访问 MyClass 中的私有成员 privateMember

友元类的存在使得特定的类能够共享私有成员,这在某些情况下可能很有用,但同时也可能破坏了封装性。因此,在使用友元类时需要权衡利弊,并确保其使用符合设计原则和需要。


五、内部类

内部类定义在另一个类内部的类,可以直接访问外部类的私有成员,而不需要通过对象来实现。

下面是一个简单的示例:

class Outer {
private:
    int outerPrivate;

public:
    class Inner {
    public:
        void display(const Outer& outer) {
            std::cout << "Inner class accessing outerPrivate: " << outer.outerPrivate << std::endl;
        }
    };

    Outer(int value) : outerPrivate(value) {}

    void callInner() {
        Inner inner;
        inner.display(*this);
    }
};

int main() {
    //通过callInner调用display
    Outer outerObj(42);
    outerObj.callInner();

    //创建inner对象调用display
    Outer::Inner innerObj;
    innerObj.display(outerObj);
    return 0;
}

在这里插入图片描述


六、匿名对象

匿名对象是指在创建对象时不指定对象名的对象。在对象的类型后面直接加上一对括号可以创建匿名对象,而不提供对象名。

匿名对象没有对象名,只能在创建的语句中使用,并且通常在该语句执行结束后就会被销毁。

class MyClass {
public:
    void display() {
        std::cout << "Object is displayed." << std::endl;
    }
};

int main() {
    // 创建匿名对象,并调用其成员函数
    MyClass().display();
    
    return 0;
}

在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

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

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

相关文章

QT上位机:串口调试助手

前言 上位机的简单编写可以帮我们测试并完善平台&#xff0c;QT作为一款跨平台的GUI开发框架&#xff0c;提供了非常丰富的常用串口api。本文先从最简单的串口调试助手开始&#xff0c;编写平台软件的串口控制界面 工程配置 QT 串口通信基于QT的QSerialPort类&#xff0c;先在…

python_蓝桥杯刷题记录_笔记_全AC代码_入门5

前言 关于入门地刷题到现在就结束了。 题单目录 1.P1579 哥德巴赫猜想&#xff08;升级版&#xff09; 2.P1426 小鱼会有危险吗 1.P1579 哥德巴赫猜想&#xff08;升级版&#xff09; 一开始写的代码是三重循环&#xff0c;结果提交上去一堆地TLE&#xff0c;然后我就给减少…

六轴机器人奇异点

1 奇异点说明 有着6个自由度的KUKA机器人具有3个不同的奇点位置。即便在给定状态和步骤顺序的情况下,也无法通过逆向变换(将笛卡尔坐标转换成极坐标值)得出唯一数值时,即可认为是一个奇点位置。这种情况下,或者当最小的笛卡尔变化也能导致非常大的轴角度变化时,即为奇点位置…

如何使用C#调用LabVIEW算法

新建一个工程 这是必须的&#xff1b; 创建项目 项目 点击完成&#xff1b; 将项目另存为&#xff1b;方便后续的使用&#xff1b; 创建 一个测试VI 功能很简单&#xff0c;用的一个加法&#xff1b;将加数A&#xff0c;B设置为输入&#xff0c;和C设置为输出&#xff0c;…

燃油宝行业分析:前景广阔市场潜力巨大

燃油宝&#xff0c;是第三代汽油清净剂的一种俗称(也被称为&#xff0c;汽油清净剂或燃油添加剂)&#xff0c;其目的是解决电喷车型燃油系统的积碳问题&#xff0c;快速恢复发动机最佳工况。 燃油宝对于清洁燃油系统、改善喷油雾化和燃油的充分燃烧、降低排放确实有显著效果&am…

【PyQt】05-多线程

文章目录 前言一、什么是单线程、多线程二、代码现象示例多线程代码运行结果 总结 前言 文章开始还是解释一下&#xff0c;这是跟着王铭东老师学习的。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、什么是单线程、多线程 单线程 在Python中&am…

Leetcode第383场周赛

Leetcode第383场周赛 本人水平有限&#xff0c;只做前3道。 一、边界上的蚂蚁 边界上有一只蚂蚁&#xff0c;它有时向 左 走&#xff0c;有时向 右 走。 给你一个 非零 整数数组 nums 。蚂蚁会按顺序读取 nums 中的元素&#xff0c;从第一个元素开始直到结束。每一步&#…

百面嵌入式专栏(面试题)内存管理相关面试题1.0

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍内存管理相关面试题 。 一、内存管理相关面试题 page数据结构中的_refcount和_mapcount有什么区别?匿名页面和高速缓存页面有什么区别?page数据结构中有一个锁,我们称为页锁,请问trylock_page()和loc…

20240206三次握手四次挥手

TCP和UDP异同点 相同点&#xff1a;同属于传输层的协议 不同点&#xff1a; TCP ----> 稳定 1> 提供面向连接的&#xff0c;可靠的数据传输服务 2> 传输过程中&#xff0c;数据无误、数据无丢失、数据无失序、数据无重复 1、TCP会给每个数据包编上编号&#xff…

HGAME 2024 WEEK1 WP

文章目录 WEBezHTTPBypass itSelect Courses2048*16jhat REezASMezPYCezUPXezIDA PWNEzSignIn CRYPTO奇怪的图片ezRSAezMathezPRNG MISCSignIn来自星尘的问候simple_attack希儿希儿希尔签到 放假比较闲&#xff0c;打打比赛 WEB ezHTTP 来自vidar.club、UA要求阿巴阿巴阿巴…

(每日持续更新)jdk api之ObjectInputFilter基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

“SET key value [EX seconds] [PX milliseconds] [NX|XX]“和redis分布式锁

一、可选参数介绍 EX second &#xff1a;设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。PX millisecond &#xff1a;设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key milliseco…

【QT】VS-code报错:LNK2019: 无法解析的外部符号

目录 0.环境 1.问题简述 2.分析报错原因 3.解决方法 1&#xff09;set() 相关语句 2&#xff09;target_link_libraries() 相关语句 4.参考 0.环境 windows11 、 vs-code 、 qt 、 c、编译器为vs2019-x86_amd64 1.问题简述 项目编译release版本时会报错&#xff1a;报错…

代码随想录算法训练营第十四天 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和

代码随想录算法训练营第十四天 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和 文章目录 代码随想录算法训练营第十四天 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和1 LeetCode 110.平衡二叉树2 LeetCode 257.二叉树的所有路径3 LeetCode 404.左叶子之和…

浅析一款非驱动考试网关程序(一)

前言 监考程序需要对网络流量进行过滤&#xff0c;不允许除了考试网站以外的其他网站的访问。其实就是实现了一个小型的网关程序&#xff0c;一般地有驱动实现和非驱动实现两种方式。本文只针对一款简易的非驱动实现的监考程序进行分析。 注意&#xff1a;本文通过对某考试监…

第十篇【传奇开心果系列】Python的OpenCV技术点案例示例:图像分割

传奇开心果短博文系列 系列短博文目录Python的OpenCV技术点案例示例系列短博文目录一、前言二、OpenCV图像分割介绍三、OpenCV分割算法示例代码四、归纳总结系列短博文目录 Python的OpenCV技术点案例示例系列 短博文目录 一、前言 OpenCV是一个广泛应用于计算机视觉和图像处…

2023年09月CCF-GESP编程能力等级认证Python编程五级真题解析

Python等级认证GESP(1~6级)全部真题・点这里 一、单选题(共15题,共30分) 第1题 近年来,线上授课变得普遍,很多有助于改善教学效果的设备也逐渐流行,其中包括比较常用的手写板,那么它属于哪类设备?( ) A:输入 B:输出 C:控制 D:记录 答案:A 第2题 以下关于…

计算机服务器中了mkp勒索病毒如何解密,mkp勒索病毒解密流程

随着网络技术的不断发展与应用&#xff0c;越来越多的企业走向数字化办公模式&#xff0c;计算机极大地方便了企业的正常生产运营&#xff0c;但网络威胁的手段也不断增加。近期&#xff0c;云天数据恢复接到很多企业的求助&#xff0c;企业的计算机服务器遭到了mkp勒索病毒攻击…

Qt 常见容器类用法(一)

目录 QMap类 QHash类 QVector类 QMap类 QMap<key,T>提供一个从类型为Key的键到类型为T的值的映射。通常&#xff0c;QMap存储的数据形式是一个键对应一个值&#xff0c;并且按照键Key的次序存储数据。为了能够支持一键多值的情况&#xff0c;QMap提供QMap<key,T&g…

相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…