C++学习笔记03-对象和类(问题-解答自查版)

前言

以下问题以Q&A形式记录,基本上都是笔者在初学一轮后,掌握不牢或者频繁忘记的点

Q&A的形式有助于学习过程中时刻关注自己的输入与输出关系,也适合做查漏补缺和复盘。

本文对读者可以用作自查,答案在后面,需要时自行对照。

--

问题集

Q1:这组程序中,两个static变量哪个是长期在内存的?

Q2:C++中,内部链接性和外部链接性有什么区别?

Q3:#pragma once 以及 #ifndef ... #define xx_H_ ... #endif 的作用?

Q4:结构体和class的区别?

Q5:拷贝构造函数是干什么用的?定义的固定格式?(入参?)

Q6:以下程序中哪些试图调用构造函数的方式是正确的?

 Q7:以下程序调用几次拷贝构造?

void callPerson(Person p){return ;
}
int main(){Person p1;callPerson(p1);return 1;
}

Q8:以下程序调用几次拷贝构造?(区别是返回类型是Person

Person callPerson(Person p){return p;
}int main(){Person p1;callPerson(p1);return 1;
}

Q9:构造函数调用规则如下:

        如果用户定义有参构造函数,则不在提供默认无参构造,但是会提供默认拷贝构造

        如果用户定义拷贝构造函数,c++默认不会再提供其他构造函数;

问题:如果我 Person p1 = p2,这个时候除了会调用拷贝构造函数,还会调用其他构造函数吗?(假设有定义~)

Q10:浅拷贝和深拷贝的定义?编译器默认提供的拷贝构造函数是什么样子的?

Q11:浅拷贝的bug是什么?

Q12:深拷贝的具体操作?

Q13:这个构造函数的语法?

class Person
{
public:int age;string name;Person():age(10),name("default") {cout<<"gz"<<endl;}...
}

Q14:this指针的用法之一是防止冲突,还有什么作用?

Q15:这个类内成员函数的语法?

Q16:const Person p; 这个p能否调用

Q17:想想链表中的有参构造会怎么做?如何优雅的写出来带默认初始值的构造函数?

Q18:C++中支不支持类中类?

Q19:友元中的friend可以这么用吗?

int main(){friend p = Person();return 0;
}

Q20:友元的两个比较常用的操作

Q21:类外定义函数?可以定义构造函数吗?

Q22:运算符重载的本质?

Q23:运算符重载的两种方式?类内重载&全局重载?为什么要学习全局重载?

Q24:这个重载<<的操作正确吗?为什么要返回 ostream& 类型?

// 类外定义<<重载
ostream& Person::operator<<(ostream &out, const Person &p2){}


参考解答

Q1:这组程序中,两个static变量哪个是长期在内存的?

A1:都在,而且全局外的 int global 和这俩,都是长期在内存中的。即使不调用 funct1(),具体参考下表

Q2:C++中,内部链接性和外部链接性有什么区别?

A2:在C++中,链接性(Linkage)指的是变量、函数或模板等实体在不同编译单元(Translation Unit)之间的可见性和可用性。

1)外部链接性(External Linkage,如 int global )

        具有外部链接性的实体可以在多个编译单元中被定义和使用。(多个文件中共享编译)

        这些实体在编译后生成的可执行文件或库文件中具有全局唯一性。

        例如,如果你在一个编译单元中声明了一个具有外部链接性的全局变量或函数,然后在另一个编译单元中引用它,编译器会链接到同一个全局实体。

        通常,全局变量和函数默认具有外部链接性,除非它们被声明为static。

2)内部链接性(Internal Linkage,如 static int global

        具有内部链接性的实体仅在其定义的编译单元内部可见。(仅当前cpp)

        这意味着即使在其他编译单元中声明了相同名称的实体,它们也会被视为不同的实体。

        内部链接性可以通过在全局变量或函数前加上static关键字来实现,这会限制其作用域仅在定义它的编译单元内

        这有助于避免命名冲突,并可以用于实现编译单元内私有的全局变量或函数。

Q3:#pragma once 以及 #ifndef ... #define xx_H_ ... #endif

        这两套东西是用来做什么的?

A3:#pragma once#ifndef ... #define ... #endif 都是用来防止头文件被多次包含的机制

        1. #pragma once 是一种非标准的、但广泛支持的预处理指令,用于指示编译器只包含一次头文件。当编译器遇到 #pragma once 时,它会确保该文件在整个编译单元中只被包含一次。这种方式简单且有效,但因为它不是C/C++标准的一部分,所以可能在某些编译器上不被支持

        2. #ifndef ... #define ... #endif 是一种标准的防止头文件重复包含的方法,通过宏定义来实现。具体步骤如下:
           - `#ifndef` 检查是否已经定义了某个宏(通常是头文件的名称,后缀 `_H_` 或 `_H` 是一种常见习惯)。
           - `#define` 如果没有定义,则定义该宏。
           - `#endif` 结束条件编译块。  

   // example.h#ifndef EXAMPLE_H_  // 如果没有定义 EXAMPLE_H_#define EXAMPLE_H_    // 定义 EXAMPLE_H_// 头文件内容#endif // EXAMPLE_H_

        第二种方式是标准的,可以在所有支持C/C++的编译器上工作。而 `#pragma once` 虽然在大多数现代编译器上都有效,但因为它不是标准的一部分,所以可能在某些特定情况下不被支持。在编写可移植性要求较高的代码时,推荐使用 `#ifndef ... #define ... #endif` 的方式


对象和类

Q4:结构体和class的区别?

A4:OOP中,主要是权限。struct 一个 a对象 和 class b对象

        a.属性 默认是public的,直接可以访问。

        b.属性 默认是private的,不可以直接访问。

Q5:拷贝构造函数是干什么用的?定义的固定格式?(入参?)

A5:就是 class Person中,让p1 = p2的。

        这样在初始化的时候,p1就可以顺承所有p2的基本信息。

        另外需要注意,使用场景可以是

        1)值传递一个入参为 class  Person p 的函数,此时会调用一次拷贝构造函数。(传参嘛,肯定要拷贝一个副本)

        2)return返回如果是 class  Person p 的话,

Q6:以下程序中哪些试图调用构造函数的方式是正确的?

A6:除了第二行都正确,第二行是会被编译器认为是声明了一个返回值为Person,没有参数的函数

这里有个比较重要的点:C#和C++很不一样的一个地方

        C++ 中 Person p1 就会调用构造函数

        C# 中,只有new的方法才会调用构造函数

Q7:以下程序调用几次拷贝构造?

void callPerson(Person p){return ;
}
int main(){Person p1;callPerson(p1);return 1;
}

A7:一次,原因是p1值传递,建立一个临时变量用来存储p1的副本

Q8:以下程序调用几次拷贝构造?(区别是返回类型是Person)

Person callPerson(Person p){return p;
}int main(){Person p1;callPerson(p1);return 1;
}

A8:两次,在这段代码中,

        当main函数调用callPerson函数时,p1作为参数传递。建立一个临时变量用来存储p1的副本,这是拷贝构造函数第一次被调用。

        由于返回类型是Person,编译器会创建一个新的Person对象,这个对象是p的拷贝,然后将其作为函数的返回值。这是拷贝构造函数第二次被调用。

        所以,总共调用了两次拷贝构造函数。第一次是在调用callPerson时,第二次是在callPerson返回时。

Q9:构造函数调用规则如下:

        如果用户定义有参构造函数,则不在提供默认无参构造,但是会提供默认拷贝构造

        如果用户定义拷贝构造函数,c++不会再提供其他构造函数;

        问题:如果我 Person p1 = p2,这个时候会调用拷贝构造函数,还会调用构造函数吗?(假设有定义~

A9:不会了。实践出真知。可能就是没必要吧

Q10:浅拷贝和深拷贝的定义?编译器默认提供的拷贝构造函数是什么样子的?

A10:浅拷贝:赋值,即a = b;    深拷贝:在堆区重新申请空间,进行赋值操作;

编译器默认提供的拷贝构造函数是浅拷贝,也就是说我们什么都不写,会有 m_data = data 的操作

Q11:浅拷贝容易的bug是什么?

A11:浅拷贝最容易遇到的问题是容易造成指针所指向资源的重复释放。

两个解决方法 1)浅拷贝用 !=NULL 避免二次释放  2)采用深拷贝

Q12:深拷贝的具体操作?

A12:

Q13:这个构造函数的语法?

class Person
{
public:int age;string name;Person():age(10),name("default") {cout<<"gz"<<endl;}...
}

A13:初始化列表,比较常用

Q14:this指针的用法之一是防止冲突,还有什么作用?

A14:this指针始终指向调用成员方法的对象本身。其本身是一个const class *p

        除了 this->age = age 的使用以外,还有定义成员方法时,通过返回 Person & 的方法 使用 return *this

        这种情况下可以有 func().func().func(). 这种链式调用。

        注意:为什么成员函数的返回类型 一定要是 Person & 而不是Person ?

                原因是:Person func() 的方式 return的是对象的拷贝副本,而不是对象本身。如果没有return获取到对象本体,那么程序逻辑就会出现错误。

        附:一个自己写的可以被链式调用的LinkList方法(虽然有瑕疵,他并不安全hh):

    LinkNode & AddBackNode(LinkNode &target){  // unsafeLinkNode *src = this;target.next = src->next;src->next = &target;return target;}

Q15:这个类内成员函数的语法?

A15:常函数,使用这个语法之后 this->属性 就不再能够改变。看着不是很优雅,但是const实在没更合适的地方加了

        常函数的语法只能在class中使用。

        常函数的主要含义是:这个函数将不能改变class中的任何成员属性。

Q16:const Person p; 这个p能否调用 Person 类中一个修改了成员属性的函数?

        进一步地,能否调用 Person 类中,一个访问了成员属性的朴素函数?

A16:均不可以。常对象只能调用常函数(见Q15)

Q17:想想链表中的有参构造会怎么做?如何优雅的写出来带默认初始值的构造函数?

A17:这个东西学名叫做初始化列表

        LinkNode() : val(0), next(nullptr){}LinkNode(int x) : val(x), next(nullptr){}

Q18:C++中支不支持类中类?

A18:支持。比如刷算法题时,我们会在定义链表LinkList的时候,从中建立一个LinkNode类

        这样可以把对于链表的管理(如:dummyHead和size)和节点的管理(val和next)分离开。

Q19:友元中的friend可以这么用吗?

int main(){friend p = Person();return 0;
}

A19:显然不行,friend只能在类内声明

Q20:友元的两个比较常用的操作:

1)全局函数做友元:先在原来类中声明friend,再编写全局函数,这个全局函数就可以访问到private属性

2)友元类:这个类内部的成员方法可以访问private属性

Q21:类外定义函数?可以定义构造函数吗?

A21:可以,就是要表明是哪个类(这个 Person:: 学名作用域)

class Person{Person();  //这里是声明
public:int score;
};// 类外定义构造函数
Person::Person():score(0){}

Q22:运算符重载的本质?

A22:运算符实际上是C++为编程者预设了一个合乎规范的函数名(operator+;operator<< 等)

以下两个格式的调用语句等价:

    p3 = p1 + p2;

    p3 = p1.operator+(p2);

Q23:运算符重载的两种方式?类内重载&全局重载?为什么要学习全局重载?

A23:我们假设有Person类,首先,两种重载的方式都支持 p3 = p1 + p2 的最终写法

                全局重载:有些时候无法在类内达成重载的效果,比如重载 "<<",我们写在类内,只能达到 P<<... 的效果

而对于 cout << P,就不能完成了,必须通过全局函数对运算符进行重载(见Q24)

Q24:这个重载<<的操作正确吗?为什么要返回 ostream& 类型?

// 类外定义<<重载
ostream& Person::operator<<(ostream &out, const Person &p2){}

A24:不对,这样会报错 Person类中没有成员 operator<<,定义的格式错了,正确格式应该是:

ostream& operator<<(ostream &out, Person &p){out << p.score << endl;  // 选择我们想要给流输出的内容return out;
}

返回类型:ostream& 这个返回的类型确保我们可以 cout << P << endl; 这也是一种链式调用的设计

入参:分别是 ostream &out, Person &p,只有这样的一前一后,才能对应 “cout << P” 的格式。


 

Q25:可以被重载的运算符大概有哪些?了解即可

A25:

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

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

相关文章

C#,.NET常见算法

1.递归算法 1.1.C#递归算法计算阶乘的方法 using System;namespace C_Sharp_Example {public class Program{/// <summary>/// 阶乘&#xff1a;一个正整数的阶乘Factorial是所有小于以及等于该数的正整数的积&#xff0c;0的阶乘是1&#xff0c;n的阶乘是n&#xff0…

高效部署Modbus转MQTT网关:Modbus RTU、Modbus TCP转MQTT

钡铼Modbus转MQTT网关&#xff0c;简而言之&#xff0c;就是通过将Modbus协议&#xff08;包括Modbus RTU和Modbus TCP&#xff09;的数据转换为MQTT协议的数据格式&#xff0c;从而实现设备数据的上传和云端控制指令的下发。这一转换过程使得设备能够与基于MQTT协议的云平台进…

Harmony Next -- 通用标题栏:高度自定义,可设置沉浸式状态,正常状态下为:左侧返回、居中标题,左中右均可自定义视图。

hm_common_title_bar OpenHarmony三方库中心仓&#xff1a;https://ohpm.openharmony.cn/#/cn/detail/common_title_bar 介绍 一款通用标题栏&#xff0c;支持高度自定义&#xff0c;可设置沉浸式状态&#xff0c;正常状态下为&#xff1a;左侧返回、居中标题&#xff0c;左…

Vue3分段控制器(Segmented)

效果如下图&#xff1a;在线预览 APIs Segmented 参数说明类型默认值必传block是否将宽度调整为父元素宽度&#xff0c;同时所有选项占据相同的宽度booleanfalsefalsedisabled是否禁用booleanfalsefalseoptions选项数据string[] | number[] | SegmentedOption[][]falsesize控…

Vivado生成网表文件并创建自定义IP

平台&#xff1a;vivado2018.3 应用场景&#xff0c;在设计的过程中&#xff0c;我们一些特定的模块需要交付给别人&#xff0c;但是又不想让他们看到其中的源码。就可以将源码封装成网表和IP文件。 vivado生成网表文件 设置综合。设置-flatten_hierarchy* 为full。 这里可…

基于ansible进行运维自动化的研究以及相关的属性

一、ansible-简介 介绍 ansible是新出现的自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c; 实现了批量系统配置、批量程序部署、批量运行命令等功能。 无客户端。 …

【香橙派开发板测试】:在黑科技Orange Pi AIpro部署YOLOv8深度学习纤维分割检测模型

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ Orange Pi AIpro开发板相关介绍1.1 &#x1f393; 核心配置1.2 ✨开发板接口详情图1.3 ⭐️开箱展示 二、2️⃣配置开发板详细教程2.1 &#x1f393; 烧录镜像系统2.2 ✨配置网络2.3 ⭐️使用SSH连接主板 三、…

为什么 FPGA 的效率低于 ASIC?

FPGA是“可重构逻辑”器件。先制造的芯片&#xff0c;再次设计时“重新配置”。 ASIC 不需要“重新配置”。你先设计&#xff0c;把它交给代工厂&#xff0c;然后制造芯片。 现在让我们看看这些芯片的结构是什么样的&#xff0c;以及它们的不同之处。 ● 逻辑单元&#xff1a;F…

小程序多排数据横向滚动实现

如何实现多排数据滚动效果 swiper 外部容器 swiper-item 每一页的数据 因为现在有多排数据,现在在swiper-item 中需要循环一个数组 初版 <template><view><view class"container"><view class"swiper-box"><swiper class&qu…

拍得更近、拍得更清:Pura 70 Pro如何做到5cm对焦?

众所周知&#xff0c;我们的眼睛离一个物品越近时&#xff0c;我们就越能看清该物品的细节&#xff0c;但物品距离超过某个极限时&#xff0c;反而会看不清楚——这是因为超出了眼睛所能对焦的极限。 对于手机摄像头来说&#xff0c;也具有相似的道理。当我们的手机镜头距离被…

windows server报错--无法启动此程序,因为计算机中丢失MSVCP120.dll解决办法(已解决)

无法启动此程序&#xff0c;因为计算机中丢失MSVCP120.dll解决办法。 win7系统丢失MSVCP120.dll解决方法&#xff1a; 1、安装微软常用运行库合集&#xff0c;就可以完美的解决&#xff0c;此C运行库算是很全了&#xff0c;安装它才免于重装系统&#xff0c;完美的解决了我的丢…

【elementui】记录el-table设置左、右列固定时,加大滚动条宽度至使滚动条部分被固定列遮挡的解决方法

当前elementui版本&#xff1a;2.8.2 现象&#xff1a;此处el-table__body-wrapper默认的滚动条宽度为8px&#xff0c;我加大到10px&#xff0c;如果不设置fixed一切正常&#xff0c;设置fixed后会被遮挡一点 el-table__fixed-right::before, .el-table__fixed::before 设置…

CentOS7使用Postfix, Dovecot搭建邮箱服务

CentOS7使用Postfix&#xff0c;Dovecot搭建邮箱服务的步骤与挑战&#xff1f; 为了满足企业内部或个人的邮件服务需求&#xff0c;使用CentOS7搭建一个稳定、安全的邮箱服务器是一个非常实用的解决方案。AokSend将详细介绍如何在CentOS7系统上使用Postfix和Dovecot搭建邮箱服…

linux系统进程占cpu 100%解决步骤

1.查找进程 ps aux 查看指定进程: ps aux | grep process_name2.根据进程查找对应的主进程 pstree -p | grep process_name 3.查看主进程目录并删除 ps -axu | grep process_name rm -rf /usr/bin/2cbbb

修改 Tomcat 默认端口号最简单的方法

前言 每次在创建一个新的Maven项目之后&#xff0c;启动项目总会报8080端口号被占用的问题&#xff0c;既然每次都有这样的困扰&#xff0c;那不如一了百了&#xff0c;直接修改默认的8080端口号。 &#xff08;如果还是想要默认端口号。可参考我主页文章杀死占用了8080的进程…

IB user verbs介绍

本文来自对内核源代码文档/Documentation/infiniband/user_verbs.rst的翻译和理解。 在Infiniband设备帮助下&#xff0c;跨计算机的两个进程可以相互访问对方的虚地址空间。在Linux操作系统上&#xff0c;支持进程能直接访问本地Infiniband设备的资源&#xff0c;从而实现跨机…

openmv学习笔记(24电赛笔记)

#opemv代码烧录清除详解 openmv的代码脱离IDE运行程序&#xff0c;只需要在IDE中将代码烧录道flash里面&#xff0c;断开IDE连接&#xff0c;上电之后&#xff0c;会自动执行main.py中的程序&#xff0c;IDE烧录的时候&#xff0c;会默认将程序后缀保存为 .py文件。 ​​​​​…

防爆智能手机如何助力电气行业保驾护航?

在电气行业的智能化转型浪潮中&#xff0c;防爆智能手机以其强大的数据处理能力、实时通讯功能及高度集成的安全特性&#xff0c;正成为保障电力网络稳定运行、预防安全隐患的得力助手。 防爆智能手机在电气行业中发挥着重要的保驾护航作用&#xff0c;主要体现在以下几个方面&…

swagger-ui.html报错404

问题1&#xff1a;权限受限无法访问 由于采用的Shiro安全框架&#xff0c;需要在配置类ShiroConfig下的Shiro 的过滤器链放行该页面&#xff1a;【添加&#xff1a;filterChainDefinitionMap.put("/swagger-ui.html", "anon");】 public ShiroFilterFact…

node+mysql实现(账户密码,阿里云短信验证,QQ邮箱注册登录,短信验证密码重置,邮箱密码重置)之注册,登录密码重置总篇

node+mysql实现账户登录 注意效果图项目插件代码参数说明短信验证模块邮箱验证模块注册方式登录方式密码重置前端页面部分登录页面账户登录页面(login.html)短信验证登录页面(smsLogin.html)邮箱登录页面(emailLogin.html)注册部分页面短信验证注册页面(register.html)邮…