【C++游记】类和对象下——构造函数还有你不知道的细节、静态成员、友元函数、编译器如何优化

【C++游记】类和对象下——构造函数还有你不知道的细节、静态成员、友元函数、编译器如何优化

 

枫の个人主页

你不能改变过去,但你可以改变未来

算法/C++/数据结构/C

Hello,这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕,我们继续来学习C++的内容呀。C++是接近底层有比较经典的语言,因此学习起来注定枯燥无味,西游记大家都看过吧~,我希望能带着大家一起跨过九九八十一难,降伏各类难题,学会C++,我会尽我所能,以通俗易懂、幽默风趣的方式带给大家形象生动的知识,也希望大家遇到困难不退缩,遇到难题不放弃,学习师徒四人的精神!!!故此得名【C++游记】
 话不多说,让我们一起进入今天的学习吧~~~

1>>再看构造函数

        之前的构造函数还有一点点细节没说,今天咱再对它进行补充。

1.构造函数初始化还有一种方式,就是初始化列表。初始化列表以一个冒号开始,然后是一个个逗号进行分隔的数据成员列表,每个成员变量后跟一个括号中的初始值或者表达式。如_day(5),初始化天数为5。

2.每个成员变量在初始化列表中只能出现一次,也就是唯一性。初始化列表是所有成员变量定义初始化的地方。

3.有三类成员变量(引用、const、无默认构造)必须放在初始化列表进行初始化。

4.C++11支持成员变量在声明的时候给初始值,这个初始值主要是给没在初始化列表的成员变量使用的。

5.简单来说,能用初始化列表就用初始化列表进行初始化工作。

6.初始化列表按照成员变量在类中声明的顺序进行初始化,跟初始化列表顺序无关。

总结: 所有构造函数都有初始化列表。所有成员变量都要走初始化列表进行初始化。

#include<iostream> using namespace std; class D1 { public: D1(int year = 1, int month = 1, int day = 1) :_year(year) , _month(month) , _day(day) { } void print()const { cout << _year << " " << _month << " " << _day << endl; } private: int _year; int _day; int _month; }; int main() { D1 a; a.print(); return 0; }

 

结果为1 1 1 答案正确,这就是初始化列表啦~~

2>>static成员

        降伏了初始化列表,接下来继续打static静态怪吧~
1.用static修饰的成员变量叫静态成员变量,静态成员变量一定要在类外面初始化。为什么?因为之前我们说过类独属一个域,静态成员变量在静态区,所以要在类外面初始化。

2.静态成员变量为所有类对象共享,不属于任何一个具体的对象。

3.静态成员函数没有this指针。

4.静态成员函数可以访问其他的静态成员,但不能访问非静态的,因为没有this指针。

5.非静态的成员函数,可以访问任意的静态成员变量和函数。

6.访问静态成员要突破类域,也就是类似于命名空间的类名::静态成员或对象名.静态成员来访问。

7.静态成员受访问限定符限制。

8.静态成员变量不能在声明位置初始化,因为它不属于任何一个对象。
#include<iostream> using namespace std; class D1 { public: D1(int year = 1, int month = 1, int day = 1) :_year(year) , _month(month) , _day(day) { } void print()const { cout << _year << " " << _month << " " << _day << endl; } private: int _year; int _day; int _month; static int person;//需要在类外初始化 }; int D1::person = 1;//初始化记得带上类名 int main() { D1 a; a.print(); return 0; }

3>>友元函数

打完static,又出现了友元怪,小怪好多呀~师傅加把劲!
1.友元是突破类域的一种方式,友元分为:友元函数和友元类。使用方式是在函数声明或者类声明前面加friend,还要把友元的声明放到一个类中。

2.外部友元函数可以访问类的私有和保护成员,它是一个声明,并不是类的成员函数。可以理解为非常好的朋友,你对我干什么都可以。

3.友元可以在类中任意位置定义。

4.一个函数可以是多个类的友元。

5.友元类中的成员函数都可以是另一个类的友元函数。

6.友元类的关系是单向的。我的友元函数是你,意味着你可以随意用我东西,但是我不能随意用你东西。

7.偶尔方便可以使用,但它会增加耦合度,破坏封装。
#include<iostream> using namespace std; class B;//必须有前置声明,否则A都不认识B,vb从上往下执行。 class A { friend void print(const A& aa, const B& bb);//定义aa代替传进来的类变量,bb代替第二个类变量 private: int _a1 = 11; int _a2 = 22; }; class B { friend void print(const A& aa, const B& bb);//定义aa代替传进来的类变量,bb代替第二个类变量 private: int _b1 = 111; int _b2 = 222; }; void print(const A& aa, const B& bb) {//定义aa代替传进来的类变量,bb代替第二个类变量 cout << aa._a1 << endl; cout << bb._b1 << endl; } int main() { A a; B b; print(a, b); return 0; }

#include<iostream> using namespace std; class A { friend class B; private: int _a1 = 11; int _a2 = 22; }; class B { public: void print(const A& aa) {//定义aa代替传进来的类变量,因为A是B的友元,所以B可以访问A的成员变量 cout << aa._a1 << endl; cout << _b1 << endl; } private: int _b1 = 111; int _b2 = 222; }; int main() { A a; B b; b.print(a); return 0; }

4>>编译器的优化

最后的boos战,师傅加把劲!
1.编译器日新月异,在提高版本的过程中进行了一系列的优化,在不影响结果的情况下,会减少部分传参和传值的拷贝构造。

2.编译器的不同会进行不同的优化,连续的拷贝构造会合并成一个拷贝构造。

3.想看具体过程有两个办法,一是在Linux下关闭构造优化,命令为g++ test.cpp -fno-elide-constructors 二是使用较老的编译器,这时候都没有进行更新,也就没有优化的概念。

#include<iostream> using namespace std; class A { public: A(int a = 1) :_a1(a) { cout << "A(int a)" << endl; } A(const A& aa) :_a1(aa._a1)//拷贝构造的初始化列表 { cout << "A(const A& aa)" << endl; } ~A() { cout << "~A()" << endl; } private: int _a1 = 11; }; void f1(A aa) { } int main() { //匿名对象,也就是直接给A赋值,生命周期只有这一行,构造一次,函数内右构造一次还要拷贝一次,然后析构 f1(A(1));//连续的构造加拷贝构造会优化为一个构造 return 0; }

 

 5>>结语

        今日C++到这里就结束啦,如果觉得文章还不错的话,可以三连支持一下。感兴趣的宝子们欢迎持续订阅小枫,小枫在这里谢谢宝子们啦~小枫の主页还有更多生动有趣的文章,欢迎宝子们去点评鸭~C++的学习很陡,时而巨难时而巨简单,希望宝子们和小枫一起坚持下去~你们的三连就是小枫的动力,感谢支持~


 

Read more

Python实现 MCP 客户端调用(高德地图 MCP 服务)查询天气示例

Python实现 MCP 客户端调用(高德地图 MCP 服务)查询天气示例

文章目录 * MCP 官网 * MCP 官方文档中文版 * 官方 MCP 服务示例 * Github * MCP 市场 * 简介 * 架构 * 高德地图 MCP 客户端示例 * python-sdk 客户端 * java-sdk 客户端 MCP 官网 * https://modelcontextprotocol.io/introduction MCP 官方文档中文版 * https://app.apifox.com/project/5991953 官方 MCP 服务示例 * https://github.com/modelcontextprotocol/servers Github * python-sdk:https://github.com/modelcontextprotocol/python-sdk * java-sdk:

By Ne0inhk
43-dify案例分享-MCP-Server让工作流秒变第三方可调用服务

43-dify案例分享-MCP-Server让工作流秒变第三方可调用服务

1.前言 之前我们为大家介绍过MCP SSE插件,它能够支持MCP-server在Dify平台上的调用,从而帮助Dify与第三方平台提供的MCP-server进行无缝对接。有些小伙伴提出了疑问:既然Dify可以通过MCP SSE插件调用其他平台的MCP-server,那么Dify的工作流或Chatflow是否也能发布为MCP-server,供其他支持MCP client的工具使用呢?今天,我们将为大家介绍一款Dify插件——mcp-server,它能够实现这一功能,即将Dify的工作流或Chatflow发布为MCP-server,供其他第三方工具调用。 插件名字叫做MCP-server,我们在dify插件市场可以找到这个工具 Mcp-server 是一个由 Dify 社区贡献的 Extension 类型插件。安装后,你可以把任何 Dify 应用转变成符合 MCP 标准的 Server Endpoint,供外部 MCP 客户端直接访问。它的主要功能包括: * **暴露为 MCP 工具:**将 Dify 应用抽象为单一 MCP 工具,供外部 MCP 客户端(如

By Ne0inhk
【MCP】详细了解MCP协议:和function call的区别何在?如何使用MCP?

【MCP】详细了解MCP协议:和function call的区别何在?如何使用MCP?

本文介绍了MCP大模型上下文协议的的概念,并对比了MCP协议和function call的区别,同时用python sdk为例介绍了mcp的使用方式。 1. 什么是MCP? 官网:https://modelcontextprotocol.io/introduction 2025年,Anthropic提出了MCP协议。MCP全称为Model Context Protocol,翻译过来是大模型上下文协议。这个协议的主要为AI大模型和外部工具(比如让AI去查询信息,或者让AI操作本地文件)之间的交互提供了一个统一的处理协议。我们常用的USB TypeC接口(USB-C)统一了USB接口的样式,MCP协议就好比AI大模型中的USB-C,统一了大模型与工具的对接方式。 MCP协议采用了C/S架构,也就是服务端、客户端架构,能支持在客户端设备上调用远程Server提供的服务,同时也支持stdio流式传输模式,也就是在客户端本地启动mcp服务端。只需要在配置文件中新增MCP服务端,就能用上这个MCP服务器提供的各种工具,大大提高了大模型使用外部工具的便捷性。 MCP是开源协议,能让所有A

By Ne0inhk
【大模型系列篇】大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器

【大模型系列篇】大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器

今天我们将使用FastAPI来构建 MCP 服务器,Anthropic 推出的这个MCP 协议,目的是让 AI 代理和你的应用程序之间的对话变得更顺畅、更清晰。FastAPI 基于 Starlette 和 Uvicorn,采用异步编程模型,可轻松处理高并发请求,尤其适合 MCP 场景下大模型与外部系统的实时交互需求,其性能接近 Node.js 和 Go,在数据库查询、文件操作等 I/O 密集型任务中表现卓越。 开始今天的正题前,我们来回顾下相关的知识内容: 《高性能Python Web服务部署架构解析》、《使用Python开发MCP Server及Inspector工具调试》、《构建智能体MCP客户端:完成大模型与MCP服务端能力集成与最小闭环验证》   FastAPI基础知识 安装依赖 pip install uvicorn, fastapi FastAPI服务代码示例  from fastapi import FastAPI app

By Ne0inhk