C++常用的特性-->day05

友元的拓展语法

声明一个类为另外一个类的友元时,不再需要使用class关键字,并且还可以使用类的别名(使用 typedef 或者 using 定义)。

#include <iostream>
using namespace std;

// 类声明
class Tom;
// 定义别名
using Honey = Tom;

// 定义两个测试类
class Jack
{
    // 声明友元
    // friend class Tom;    // C++98 标准语法
    friend Tom;             // C++11 标准语法 
    string name = "jack";   // 默认私有
    void print()            // 默认私有
    {
        cout << "my name is " << name << endl;
    }
};

class Lucy
{
protected:
    // 声明友元
    // friend class Tom;    // C++98 标准语法
    friend Honey;           // C++11 标准语法 
    string name = "lucy";
    void print()
    {
        cout << "my name is " << name << endl;
    }
};

class Tom
{
public:
    void print()
    {
        // 通过类成员对象访问其私有成员
        cout << "invoke Jack private member: " << jObj.name << endl;
        cout << "invoke Jack private function: " << endl;
        jObj.print();

        cout << "invoke Lucy private member: " << lObj.name << endl;
        cout << "invoke Lucy private function: " << endl;
        lObj.print();
    }
private:
    string name = "tom";
    Jack jObj;
    Lucy lObj;
};

int main()
{
    Tom t;
    t.print();
    return 0;
}

在这里插入图片描述

类模板的友元应用

在c++98时不可以为类模板声明友元,c++11新特性是可以声明为友元的

基本用法

class Tom;

template<typename T>
class Person
{
    friend T;
};

int main()
{
    Person<Tom> p;// >>>>>>>>>> Tom类是Person类的友元
    Person<int> pp;// >>>>>>>>>>> 对于int类型的模板参数,友元声明被忽略(第6行)
    return 0;
}

复杂案例

#include<iostream>
using namespace std;
template<typename T>
class Rectangle
{
public:
    friend T;
    Rectangle(int w, int h) : width(w), height(h) {}
private:
    int width;
    int height;
};

template<typename T>
class Circle
{
public:
    friend T;
    Circle(int r) : radius(r) {}
private:
    int radius;
};

// 校验类
class Verify
{
public:
    void verifyRectangle(int w, int h, Rectangle<Verify>& r)
    {
        if (r.width >= w && r.height >= h)
        {
            cout << "矩形的宽度和高度满足条件!" << endl;
        }
        else
        {
            cout << "矩形的宽度和高度不满足条件!" << endl;
        }
    }

    void verifyCircle(int r, Circle<Verify>& c)
    {
        if (r >= c.radius)
        {
            cout << "圆形的半径满足条件!" << endl;
        }
        else
        {
            cout << "圆形的半径不满足条件!" << endl;
        }
    }
};

int main()
{
    Verify v;
    Circle<Verify> circle(30);
    Rectangle<Verify> rect(90, 100);
    v.verifyCircle(60, circle);
    v.verifyRectangle(100, 100, rect);
    return 0;
}

在这里插入图片描述

强类型枚举

枚举的缺陷

// 匿名枚举
enum {Red, Green, Blue};
// 有名枚举
enum Colors{Red, Green, Blue};

如果这个时候在main函数下执行:

cout<<"red:"<<red<<endl;//err 属于重定义

错误的原因:在这两个枚举中Red是全局可见的,所有编译器就会提示其重定义了。

强类型枚举语法

针对枚举的缺陷,C++11标准引入了一种新的枚举类型,即枚举类,又称强类型枚举(strong-typed enum)。
声明强类型枚举非常简单,只需要在 enum 后加上关键字 class

强类型枚举特性

  • 强作用域,强类型枚举成员的名称不会被输出到其父作用域空间。
  • 强类型枚举只能是有名枚举,如果是匿名枚举会导致枚举值无法使用(因为没有作用域名称)。
    转换限制,强类型枚举成员的值不可以与整型隐式地相互转换
  • 可以指定底层类型。强类型枚举默认的底层类型为 int,但也可以显式地指定底层类型
    具体方法为在枚举名称后面加上∶type,其中 type 可以是除 wchar_t 以外的任何整型。比如:
#include<iostream>
using namespace std;

enum class Color:char{ Red, Green, Blue };
enum struct Color1 { Red, Green, Blue };

int main()
{
	cout << "red:" << (int)Color::Red << endl;
	int m = (int)Color::Green;
	cout << "green:" << (int)Color::Green << endl;
	cout << "sizeof Color:char" << sizeof(Color) << endl;
	cout << "sizeof Color1:" << sizeof(Color1) << endl;

	return 0;
}

在这里插入图片描述

对原有枚举的拓展

原有枚举类型的底层类型在默认情况下,仍然由编译器来具体指定实现。但也可以跟强类型枚举类一样,显式地由程序员来指定。其指定的方式跟强类型枚举一样,都是枚举名称后面加上∶type,其中type 可以是除 wchar_t 以外的任何整型

#include<iostream>
using namespace std;


enum TestColor:char { Red='a', Green, Blue };//>>>>>>普通枚举是可以直接访问的

enum class Color:char{ Red, Green, Blue };
enum struct Color1 { Red, Green, Blue };

int main()
{
	cout << "TestColor Red:" << Red << endl
		<< "TestColor Red:" << TestColor::Red << endl;
	cout << "sizeof TestColor:" << sizeof(TestColor) << endl;

	cout << "Red:" << (int)Color::Red << endl;
	int m = (int)Color::Green;
	cout << "green:" << (int)Color::Green << endl;
	cout << "sizeof Color:char" << sizeof(Color) << endl;
	cout << "sizeof Color1:" << sizeof(Color1) << endl;

	return 0;
}

在这里插入图片描述

非受限联合体

静态类型的数据/成员在非受限联合体的使用

在c++11里面不受限的是:静态类型的成员、POD类型
对于引用还是受限制的

#include<iostream>
using namespace std;

union Test
{
    int age;
    long id;
    // int& tmp = age; // error >>>>>>>>> 非受限联合体中不允许出现引用类型
    static char c;
    static int print()
    {
        cout << "c value: " << c << endl;
        return 0;
    }
};
char Test::c;
// char Test::c = 'a';

int main()
{
    Test t;
    Test t1;
    t.c = 'b';
    t1.c = 'c';
    t1.age = 666;
    cout << "t.c: " << t.c << endl;
    cout << "t1.c: " << t1.c << endl;
    //在联合体中,所有成员共享相同的内存空间。所以,当你给某个成员赋值时,其他成员的值也会被改变
    // //在非受限联合体中静态成员变量和非静态成员变量使用的不是同一块内存
    cout << "t1.age: " << t1.age << endl;
    cout << "t1.id: " << t1.id << endl;
    t.print();
    Test::print();
    return 0;
}

在这里插入图片描述

POD类型在非受限联合体的使用

union Student 中包含了一个 string 类型成员,而 std::string 是一个复杂的类类型,具有构造函数、析构函数和其他成员函数。由于 string 类型的存在,Student 联合体不能被视为 POD 类型。

如果原本类中的是POD类型,如果这个时候添加了一段自定义的构造函数那么此时的类就不是POD类型

union Student
{
    int id;
    string name;
};

int main()
{
    Student s;//err
    return 0;
}

由于非POD类型在非受限联合体的使用,这个联合体的构造函数就会被删除。

解决方案:手动地去指定一块内存空间

即–>使用placement new

placement new

  • 使用new申请内存空间:Base* ptr = new Base;
  • 使用定位放置new申请内存空间:
    ClassName* ptr = new (定位的内存地址)ClassName;
简单案例
#include <iostream>
using namespace std;

class Base
{
public:
    Base() {}
    ~Base() {}
    void print()
    {
        cout << "number value: " << number << endl;
    }
private:
    int number;
};

int main()
{
    int n = 100;
    Base* b = new (&n)Base;// >>>>> 使用placement new指定栈内存(n的)为存储空间
    b->print();
    return 0;
}

在这里插入图片描述

  • 使用定位放置new操作,既可以在栈(stack)上生成对象,也可以在堆(heap)上生成对象,这取决于定位时指定的内存地址是在堆还是在栈上。
  • 从表面上看,定位放置new操作是申请空间,其本质是利用已经申请好的空间,真正的申请空间的工作是在此之前完成的。
  • 使用定位放置new 创建对象时会自动调用对应类的构造函数,但是由于对象的空间不会自动释放,如果需要释放堆内存必须显示调用类的析构函数。
  • 使用定位放置new操作,我们可以反复动态申请到同一块堆内存,这样可以避免内存的重复创建销毁,从而提高程序的执行效率(比如网络通信中数据的接收和发送)
复杂案例
#include<iostream>
using namespace std;
class Base
{
public:
    void setText(string str)
    {
        notes = str;
    }
    void print()
    {
        cout << "Base notes: " << notes << endl;
    }
private:
    string notes;
};

union Student
{
    Student()
    {
        new (&name)string;//选取占内存最大的
    }
    ~Student() {}

    int id;
    Base tmp;
    string name;
};

int main()
{
    Student s;
    s.name = "蒙奇·D·路飞";
    cout << "Student name: " << s.name << endl;
    s.tmp.setText("我是要成为海贼王的男人!");
    s.tmp.print();
    cout << "Student name: " << s.name << endl;//>>>>>>共用同一块内存
    return 0;
}

在这里插入图片描述

匿名的非受限联合体

在这里插入图片描述

#include<iostream>
using namespace std;
/*
    木叶村要进行第99次人口普查,人员的登记方式如下:
    - 学生只需要登记所在学校的编号
    - 本村学生以外的人员需要登记其身份证号码
    - 本村外来人员需要登记户口所在地+联系方式
*/
// 外来人口信息
struct Foreigner
{
    Foreigner(string s, string ph) : addr(s), phone(ph) {}
    string addr;
    string phone;
};

// 人口信息
class Person
{
public:
    //枚举出人员身份
    enum class Category : char { Student, Local, Foreign };
    Person(int num) : number(num), type(Category::Student) {}
    Person(string id) : idNum(id), type(Category::Local) {}
    Person(string addr, string phone) : foreign(addr, phone), type(Category::Foreign) {}
    ~Person() {}

    void print()
    {
        cout << "Person category: " << (int)type << endl;
        switch (type)
        {
        case Category::Student:
            cout << "Student school number: " << number << endl;
            break;
        case Category::Local:
            cout << "Local people ID number: " << idNum << endl;
            break;
        case Category::Foreign:
            cout << "Foreigner address: " << foreign.addr
                << ", phone: " << foreign.phone << endl;
            break;
        default:
            break;
        }
    }

private:
    Category type;
    union
    {
        int number;
        string idNum;
        Foreigner foreign;
    };
};

int main()
{
    Person p1(9527);
    Person p2("1101122022X");
    Person p3("砂隐村村北", "1301810001");
    p1.print();
    p2.print();
    p3.print();
    return 0;
}

在这里插入图片描述

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

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

相关文章

Vue3 + Vite 构建组件库的整体流程

Vue3 Vite 构建组件库的流程 本文教你如何用 Vue Vite&#xff0c;一步一步构建一个组件库并发布到 npm 的整体流程 1. 通过 vite 命令创建一个基本的项目结构&#xff08;这里选用 vue ts 的项目&#xff09; npm create vitelatest2. 在项目中创建一个 lib 目录&#xf…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

UniApp的Vue3版本中H5配置代理的最佳方法

UniApp的Vue3版本中H5项目在本地开发时需要配置跨域请求调试 最开始在 manifest.json中配置 总是报404&#xff0c;无法通过代理请求远程的接口并返回404错误。 经过验证在项目根目录创建 vite.config.js文件 vite.config.js内容: // vite.config.js import {defineConfig }…

Android OpenGL ES详解——实例化

目录 一、实例化 1、背景 2、概念 实例化、实例数量 gl_InstanceID 应用举例 二、实例化数组 1、概念 2、应用举例 三、应用举例——小行星带 1、不使用实例化 2、使用实例化 四、总结 一、实例化 1、背景 假如你有一个有许多模型的场景&#xff0c;而这些模型的…

2024数维杯问题C:脉冲星定时噪声推断和大气时间信号的时间延迟推断的建模完整思路 模型 代码结果

&#xff08;Modeling of pulsar timing noise deduction and atmospheric time delay deduction of time signals&#xff09; 脉冲星是一种连续而稳定的快速旋转的中子星&#xff0c;为它们赢得了“宇宙的李温室”的绰号。脉冲星的空间观测对深空航天器的导航和时间标准的维…

Shell基础2

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

基于微信小程序的校园超市购物系统设计与实现,LW+源码+讲解

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本超市购物系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…

【golang-技巧】-线上死锁问题排查-by pprof

1.背景 由于目前项目使用 cgo golang 本地不能debug, 发生死锁问题&#xff0c;程序运行和期待不一致&#xff0c;通过日志排查可以大概率找到 阻塞范围&#xff0c;但是不能找到具体问题在哪里&#xff0c;同时服务器 通过k8s daemonset 部署没有更好的方式暴露端口 获取ppr…

【Visual Studio】设置文件目录

打开属性 输出目录&#xff1a;$(SolutionDir)bin\$(Platform)\$(Cinfiguration)\ 中间目录&#xff1a;$(SolutionDir)bin\intermediates\$(Platform)\$(Cinfiguration)\

智谱AI清影升级:引领AI视频进入音效新时代

前几天智谱推出了新清影,该版本支持4k、60帧超高清画质、任意尺寸&#xff0c;并且自带音效的10秒视频,让ai生视频告别了"哑巴时代"。 智谱AI视频腾空出世&#xff0c;可灵遭遇强劲挑战&#xff01;究竟谁是行业翘楚&#xff1f;(附测评案例)之前智谱出世那时体验了一…

Datawhale模型压缩技术Task2之模型剪枝

模型剪枝 模型剪枝介绍何为剪枝&#xff08;What is Pruning?&#xff09;剪枝类型非结构化剪枝结构化剪枝半结构化剪枝 剪枝范围局部剪枝全局剪枝 剪枝粒度细粒度剪枝基于模式的剪枝向量级剪枝内核级剪枝通道级剪枝 为何剪枝&#xff08;Why Pruning?&#xff09;剪枝标准&a…

雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448

映像的详细信息: 雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448 索引: 1 名称: Windows 11 IoT 企业版 LTSC 2024 极简V1 26100.2448 (传统legacy资源管理器) 描述: Windows 11 IoT 企业版 LTSC 2024 极简V1 26100.2448 By YCDISM v2025 2024-11-15 大…

【Qt聊天室】客户端实现总结

目录 1. 项目概述 2. 功能实现 2.1 主窗口设计 2.2 功能性窗口 2.3 主界面功能实现 2.4 聊天界面功能实现 2.5 个人信息功能开发 2.6 用户信息界面设置功能 2.7 单聊与群聊 2.8 登录窗口 2.9 消息功能 3. 核心设计逻辑 3.1 核心类 3.2 前后端交互与DataCenter 4…

3、.Net UI库:CSharpSkin - 开源项目研究文章

CSharpSkin(C# 皮肤)是一个基于C#语言开发的UI框架&#xff0c;它允许开发者使用C#和.NET技术栈来创建跨平台的桌面应用程序。CSharpSkin框架通常用于实现具有自定义外观和感觉的应用程序界面&#xff0c;它提供了一套丰富的控件和组件&#xff0c;以及灵活的样式和布局系统。 …

JUC包中常用类解析

目录 &#xff08;一&#xff09;Callable接口 &#xff08;1&#xff09;Callable与Runnable的区别 &#xff08;2&#xff09;Future接口 2.1Futrue接口中的方法 2.2FutureTask类 &#xff08;3&#xff09;Callable接口的使用 3.1借助FutureTask运行 3.2借助线程池运…

交友问题 | 动态规划

描述 如果有n个人&#xff0c;每个人都可以保持单身或与其他人结成一对。每个人只能找一个对象。求总共有多少种保持单身或结对的方式。用动态规划求解。 输入 输入第一行t表示测试用例的数量 对于每一个测试用例, 输入一个整数n表示人数1<n<18 输出 针对每个测试用…

【WPF】Prism库学习(一)

Prism介绍 1. Prism框架概述&#xff1a; Prism是一个用于构建松耦合、可维护和可测试的XAML应用程序的框架。它支持WPF、.NET MAUI、Uno Platform和Xamarin Forms等多个平台。对于每个平台&#xff0c;Prism都有单独的发布版本&#xff0c;并且它们在不同的时间线上独立开发。…

基于Java Springboot在线音乐试听交流网站

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据库&#xff…

# 第20章 Cortex-M4-触摸屏

第20章 Cortex-M4-触摸屏 20.1 触摸屏概述 20.1.1 常见的触摸屏分类 电阻式触摸屏、电容式触摸屏、红外式触摸屏、表面声波触摸屏 市场上用的最多的是电阻式触摸屏与电容式触摸屏。红外管式触摸屏多用于投影仪配套设备。 电阻式触摸屏构成&#xff1a;整个屏由均匀电阻构成…

《 C++ 修炼全景指南:二十 》不止是链表升级!跳表的核心原理与超强性能解析

摘要 这篇博客全面解析了跳表 (Skip List) 作为一种高效的链表数据结构的特性和应用。跳表以多层链表和随机化策略实现 O(log n) 的查找、插入和删除性能&#xff0c;简化了平衡树结构中常见的复杂旋转操作。通过剖析跳表的结构设计和核心操作&#xff0c;我们探讨了其在范围查…