C++类细节,反汇编,面试题02

文章目录

  • 2. 虚函数vs纯虚函数
  • 3. 重写vs重载vs隐藏
    • 3.1. 为什么C++可以重载?
  • 4. struct vs union
    • 4.1. 为什么要内存对齐?
  • 5. static作用
  • 6. 空类vs空结构体
    • 6.1. 八个默认函数:
    • 6.2. 为什么空类占用1字节
  • 7. const作用
    • 7.1 指针常量vs常量指针vs常量指针常量
  • 8. 接口vs抽象类
  • 9. 浅拷贝vs深拷贝
    • 9.1. 深拷贝应用场景
    • 9.2. 调用拷贝构造函数的三种情况
    • 9.3. 写时拷贝
  • 10. 友元
    • 10.1. 友元函数
    • 10.2. 友元类

2. 虚函数vs纯虚函数

  • virtual修饰的成员函数就是虚函数,它允许在子类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和子类的同名函数。引入虚函数是为了动态绑定。
  • 纯虚函数除了关键字virtual外,还要 =0, 它是在基类中声明但没有定义的虚函数,要求子类必须提供实现。引入纯虚函数是为了派生接口,即子类仅仅只是继承函数的接口。

3. 重写vs重载vs隐藏

  • 重写:发生继承关系中,子类重写父类的方法。
  • 重载:发生在同一个类中,函数名相同,但参数个数或类型不同。
  • 隐藏:子类函数屏蔽了与其同名的基类函数,有以下两种情况:
    1、参数不同,基类函数被隐藏 (而不是重载)
    2、参数相同,但基类函数没有virtual关键字,基类函数被隐藏 (而不是重写)

3.1. 为什么C++可以重载?

  • C++引入了命名空间,以及作用域,比如类作用域,命名空间作用域。
  • 函数在编译期间,链接符号的时候,会在符号后追加一些特殊标识,比如add函数,变成add@123。

4. struct vs union

  • 相同:都可以将不同类型的变量组合成一个整体。
  • 区别
    • struct 里的每个成员都有自己独立的内存空间;sizeof(struct) 是内存对齐后所有成员长度的总和。
    • union 里的所有成员共享同一内存空间;sizeof(union) 是内存对齐后最大的数据成员长度。

4.1. 为什么要内存对齐?

  • 确保代码在不同平台上的兼容性。
  • 提高内存访问的效率。
  • ps:在Visual Studio中,默认对齐值8,将它与结构体中最大的数据成员长度进行比较,取两者的较小值,设定为实际对齐值。

5. static作用

  • static修饰的成员变量就是类变量,是类的所有对象共有的。
  • static修饰的成员函数就是类方法,类方法不能访问对象变量只能访问类变量,可以由类名直接调用,也可以由对象调用。
  • static修饰的局部变量就是局部静态变量,在函数内可以访问到。
  • static修饰的全局变量就是全局静态变量,是当前文件内可以访问到。
  • ps:对象变量,是每个对象单独拥有的。
  • ps:const强调值不能被修改,而static强调内存只有一份拷贝。

6. 空类vs空结构体

  • 空类:默认private。
  • 空结构体:默认public。

6.1. 八个默认函数:

  • 构造函数 【A();】
  • 析构函数 【~A();】
  • 拷贝构造函数 【A (const A&);】
  • 重载赋值运算符 【A&operator = (const A&);】
  • 重载取址运算符 【A* operator& ();】
  • 重载取址运算符const 【const A* operator& () const;】
  • 移动构造函数(C++11) 【A(A&&);】
  • 重载移动赋值运算符(C++11)【A& operator = (const A&&);】

6.2. 为什么空类占用1字节

  • 因为如果对象完全不占用内存空间,空类就无法取得实例的地址,this指针失效,因此不能被实例化。而类的定义是由数据成员和成员函数组成的,在没有数据成员情况下,还可以有成员函数,因此仍然需要实例化。

7. const作用

  • 限定变量不可修改。
  • 限定成员函数不可修改数据成员(后置const)。
  • 成员函数的返回值类型是const,则返回值不是左值(前置const)。
  • 用const对函数的参数修饰,表面是输入参数,在函数内不可写。
  • const函数只能调用const函数,非const函数可以调用const函数。

7.1 指针常量vs常量指针vs常量指针常量

  • 指针常量,即指针本身是常量,所以指针的值(内存地址)不能改变,示例如下。
    int a = 10, b = 20;
    int* const p= &a;
    p = &b;  //错误,指针存放的内存地址不可变
    *p= 100; //正确,内存地址存放的内容可以改变
  • 常量指针,即指向常量的指针,不能通过指针修改指向的内容,示例如下。
    const int a = 10;
    int b = 20;
    const int* p = &a;
    p = &b; //正确, 指针存放的内存地址可变
    *p = 100; //错误,指针指向的内容不可变
    b = 100; //正确,可以通过原来的声明修改
  • 常量指针常量,即指向常量的指针本身也是常量,不能通过指针修改指向的值,指针的值不能改变,示例如下。
    const int a = 10;
    int b = 20;
    const int* const p = &a;
    p = &b; //错误, 指针存放的内存地址不可变
    *p = 100; //错误,指针指向的内容不可变

8. 接口vs抽象类

  • 抽象类:带有纯虚函数的类。
    抽象类作用:为了扩展和重用。
  • 接口:没有数据成员;成员函数都是公有的、都是纯虚函数,虚析构函数除外;是完全抽象的类。
    接口作用:只提供了一种规范,实现接口的类必须实现接口中的所有方法。
  • 相同:都不能实例化,但可以创建指针。
  • 代码如下。
// ConsoleApplication5.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include<iostream>
using namespace std;

//抽象类
class Shape 
{
protected: 
    //数据成员:价格和面积
    double price; 
    double area; 

public:
    //构造函数
    Shape() :price(100),area(0) {} 

    //虚析构函数
    virtual ~Shape() { printf("%s\n", "Delete shape"); } 

    //纯虚函数:获取图形描述和获取价格
    virtual void getDescription() = 0; 
    virtual void getPrice() = 0;
};

//接口
class Draw
{
public:
    //虚析构函数
    virtual ~Draw() { printf("%s\n", "Delete Draw"); }

    //纯虚函数:输出图形周长
    virtual void drawLen() = 0;  
};

//具体类
class Circle : public Shape,public Draw
{
private:
    double radius; 

public:
    Circle(double r) : radius(r) { area = 3.14 * radius * radius; price = 100 + area * 6; }
    ~Circle() { printf("%s%f\n", "Delete circle with radius ",radius); }

    void getDescription() { printf("%s%f\n", "Circle with radius ",radius);}
    void getPrice(){ printf("%s%f%s%f\n", "Circle with area ", area," price ",price); }
    void drawLen() { printf("%s%f\n", "Circle with len ", 2 * 3.14 * radius); }
};



int main() {
   
    Circle c(5.0);

    Shape* s = &c; //基类(Shape)指针指向子类(Circle)对象
    s->getDescription();
    s->getPrice();
    
    Draw* d = &c;  //基类(Draw)指针指向子类(Circle)对象
    d->drawLen();

    _CrtDumpMemoryLeaks();
    return 0;
}

  • 程序执行结果,如下图。

在这里插入图片描述

9. 浅拷贝vs深拷贝

  • 浅拷贝只是将指针拷贝,指向同一块内存。
  • 深拷贝是直接将内存拷贝一份。

9.1. 深拷贝应用场景

  • 【注意】 当类成员变量是指针,为它动态分配内存时,有以下两种bug情况:
    1、若使用默认的重载赋值运算符进行浅拷贝,即a和b指向同一内存,但b曾指向的内存不会被删除,造成内存泄漏;若一方离开了它的生存空间,使用析构函数释放资源,另一方会变成悬空指针,导致未定义行为;同时当另一方调用析构函数时,会因重复释放同一堆空间而触发中断。
    2、若使用默认的拷贝构造函数进行浅拷贝,会重复释放同一内存。
    所以,为避免这两种bug情况,需要进行深拷贝。
  • 修改一个对象不会影响到另一个对象时,进行深拷贝以确保每个对象都有自己独立的数据副本。

9.2. 调用拷贝构造函数的三种情况

  • 用一个对象去初始化另一个对象时。
  • 当函数的参数是对象时,形参是实参的副本,即拷贝构造了一个新对象。
    • vs 但当函数的参数是对象引用或对象指针时,是直接传递对象this指针,无需拷贝。
  • 当函数的返回值是对象引用时,由于临时对象离开了函数就会消失,所以要对临时对象进行拷贝,构造一个新对象。【注意】 当临时对象出了函数作用域后,存放它数据的那块内存随时会被占用,写入新数据,所以在拷贝构造过程中 【存在安全隐患】,即它可能拷贝别的内容,代码和反汇编如下。
    • vs 但当函数的返回值是对象指针时,由于指针指向临时对象,所以临时对象还没消失,并且也无需进行拷贝。
    • vs 【注意】 但当函数的返回值是对象时,不一定会调用拷贝构造函数,因为C++编译器通常会进行返回值优化,即它直接传递保存返回值的对象this指针,然后在函数内直接构造,由于这个对象是在函数外定义的,所以不会受函数作用域的影响。
#include <iostream>
using namespace std;

class A {
private:
    int data;
public:
    A(int i) { data = i; } 	

    A(const A& a)
    {
        data = a.data;
        cout << "拷贝构造函数执行完毕" << endl;
    }
   
};

A& getA() {
    A a(3);
    return a;
}

int main() {
    
    A d1 = getA();      		    			
    return 0;
}

eax保存返回的临时对象地址,如下图。
在这里插入图片描述
由于临时对象的内存空间被占用了,写入了新数据,所以新对象拷贝了错误的内容,如下图。
在这里插入图片描述

9.3. 写时拷贝

  • 在使用系统重要的dll或者系统一些函数的时候,系统为了节省空间和提高性能,会直接映射一份共享地址,但当我们对其进行修改时,会触发写时拷贝,会拷贝一份给我们进程内使用,防止我们去修改共享的地址,影响整个系统。

10. 友元

  • 通过友元,普通函数或另一个类的成员函数可以访问到类的私有成员和保护成员。
  • 友元的正确使用能提高程序的运行效率,但同时也破坏了类的封装性和数据的隐藏性,导致程序可维护性变差。

10.1. 友元函数

  • friend修饰的函数就是友元函数,可以访问类中的私有成员和保护成员,只需要在类中声明。
  • 如普通函数声明友元,可以修改类的数据成员,代码如下。
class MyClass {
private:
    int privateMember;

protected:
    double protectedMember;

public:
    MyClass(int i, double d) : privateMember(i), protectedMember(d) {}

    friend void friendFunction(MyClass& obj);// 声明友元函数

    void showData(){
        cout << privateMember << " " << protectedMember << endl;
    }

};

// 定义友元函数
void friendFunction(MyClass& obj) {
    obj.privateMember = 44; 
    obj.protectedMember = 55;
}

int main() {
    MyClass obj(10,42);
    friendFunction(obj);
    
    obj.showData(); //输出44 55 
    return 0;
}

10.2. 友元类

  • friend修饰的类就是友元类,它所有成员函数都是另一个类的友元函数,即都可以访问另一个类的私有成员和保护成员。
  • 如类声明友元,都可以访问另一个类的数据成员,代码如下。
class MyClass {
private:
    int privateMember;

protected:
    double protectedMember;

public:
    MyClass(int i, double d) : privateMember(i), protectedMember(d) {}

    friend class FriendClass;  // 声明友元类

    void showData(){
        cout << privateMember << " " << protectedMember << endl;
    }

};

//定义友元类
class FriendClass
{
private:
    int value;

public:
    FriendClass() :value(0) {}

    void setValue(MyClass& obj){
        value = obj.privateMember + obj.protectedMember;
    }

    void  showValue() {
        cout << value << endl;
    }
};


int main() {
    MyClass obj(10,42);
    FriendClass objf;

    objf.setValue(obj);
    objf.showValue(); //输出52

    return 0;
}

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

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

相关文章

用友网络的危与机:2023年亏损约10亿元,王文京面临严肃拷问

“企业在新的产业浪潮来临时&#xff0c;应该主动推进新阶段的产品和业务创新&#xff0c;这样才能够在新的浪潮成为主流的时候&#xff0c;走到行业前面&#xff0c;否则就会从产业发展的潮流中掉下来”。用友网络创始人王文京&#xff0c;曾用“冲浪理论”形容一家企业成功的…

国内好用的测试用例管理工具有哪些?

目前市面上的测试用例管理工具有很多&#xff0c;但由于针对的项目、领域、目标用户&#xff0c;功能也并不一致&#xff0c;所以选择一款适合的测试管理平台并不轻松。做好这件事&#xff0c;首先要需求明确你用测试管理工具干什么&#xff1f;最终想要达到什么目标&#xff1…

C语言学习(八)typedef 虚拟内存 malloc/free

目录 一、typedef 类型重定义&#xff08;一&#xff09;使用&#xff08;二&#xff09;define和typedef的区别1. 编译处理的阶段不同2. 功能不同 二、虚拟内存&#xff08;一&#xff09;虚拟内存分布&#xff08;二&#xff09;内存分布1. 静态分配2. 动态分配 三、malloc/f…

用sunoAI写粤语歌的方法,博主已经亲自实践可行

粤语歌还是很好听的&#xff0c;那么如何使用suno进行粤语歌的创作呢&#xff1f; 本文和大家进行分享下如何进行粤语歌曲的创作。 访问地址如下&#xff08;电脑端/手机端一个地址&#xff09;&#xff1a; ​https://suno3.cn/#/?i8NCBS8_WXTT 在微信浏览器中也可以直接…

RT-DETR改进教程|加入SCNet中的SCConv[CVPR2020]自校准卷积模块!

⭐⭐ RT-DETR改进专栏|包含主干、模块、注意力机制、检测头等前沿创新 ⭐⭐ 一、 论文介绍 论文链接&#xff1a;http://mftp.mmcheng.net/Papers/20cvprSCNet.pdf 代码链接&#xff1a;https://gitcode.com/MCG-NKU/SCNet/ 文章摘要&#xff1a; CNN的最新进展主要致力于设计更…

文字转成活码的3步操作,手机扫码即可查看文本信息

现在经常会通过二维码的方式来传递通知的文字信息&#xff0c;只需要分享文字生成二维码的图片到微信群或者印刷出来&#xff0c;其他人就可以通过扫码来查看文字内容&#xff0c;有利于其他人更快速的获取信息。 目前文本静态码无法通过微信来扫码展示&#xff0c;那么想要解…

服务器被后台爆破怎么处理

服务器后台遭受密码爆破攻击是网络安全中常见的威胁之一&#xff0c;这种攻击通过不断尝试不同的用户名和密码组合来破解系统登录凭证&#xff0c;一旦成功&#xff0c;攻击者便能非法访问系统资源。 本文将介绍如何识别此类攻击&#xff0c;并采取有效措施进行防御&#xff0c…

ETL-kettle数据转换及组件使用详解

目录 一、txt文本转换成excel 1、新建、转换 2、构建流程图 3、配置数据流图中的各个组件 3.1、配置文件文本输入组件 3.2、 配置Excel输出组件 4、保存执行 二、excel转换成mysql &#xff08;1&#xff09;在MySQL数据库中创建数据库&#xff0c;这个根据自身情况。我…

(python)cryptography-安全的加密

前言 cryptography 是一个广泛使用的 Python 加密库&#xff0c;提供了各种加密、哈希和签名算法的实现。它支持多种加密算法&#xff0c;如 AES、RSA、ECC 等&#xff0c;以及哈希函数&#xff08;如 SHA-256、SHA-384 等&#xff09;和数字签名算法(如 DSA、ECDSA 等). 目录 …

一本书打通SLAM在智能汽车/自动驾驶领域应用

自动驾驶技术已成为当今数字化时代汽车行业的热点话题之一。随着技术的不断成熟&#xff0c;越来越多的车辆采用激光SLAM&#xff08;即时定位与地图构建&#xff09;和视觉SLAM技术&#xff0c;实现更高层次的智能网联汽车。SLAM技术在智能网联汽车中的应用是非常重要的&#…

[XYCTF新生赛]-PWN:baby_gift解析(函数调用前需清空eax)

查看保护 查看ida 这里有一处栈溢出&#xff0c;并且从汇编上看&#xff0c;程序将rbp0x20处设置为了rdi&#xff0c;让我们可以控制rdi的值。而程序没有可利用的pop。 完整exp&#xff1a; from pwn import* pprocess(./babygift) premote(gz.imxbt.cn,20833) printf_plt0x4…

如何通过ETL工具对数据进行去重

在数据处理流程中&#xff0c;数据去重是一个至关重要的环节&#xff0c;它能够确保数据分析的准确性和效率。ETL&#xff08;Extract, Transform, Load&#xff09;工具作为数据集成的重要组成部分&#xff0c;提供了强大的功能来帮助用户实现数据的抽取、转换和加载&#xff…

【Unity Shader入门精要 第7章】基础纹理(一)

1. 纹理映射 每一张纹理可以看作拥有一个属于自己的2D坐标空间&#xff0c;其横轴用U表示&#xff0c;纵轴用V表示&#xff0c;因此也称为UV坐标空间。 UV空间的坐标范围为[0&#xff0c;0]到[1&#xff0c;1]&#xff0c;在Unity中&#xff0c;UV空间也是从左下到右上&#…

神经网络复习--卷积神经网络及其扩展

文章目录 卷积卷积网络反向传播已知池化层误差&#xff0c;反向求上一层隐藏层误差已知卷积层的误差&#xff0c;推导该层的W, b的梯度 注意力机制Transformer卷积变体 卷积 卷积神经网络是一个多层的神经网络&#xff0c;每层由多个二维平面组成&#xff0c;每个平面由多个独…

免费pr相册模板mogrt|手机壁纸AI绘画摄影作品照片展示模板视频素材

pr相册模板mogrt&#xff0c;手机壁纸、电脑桌面壁纸、AI绘画、摄影作品、照片展示模板视频素材。 Premiere Pro 2023及以上版本。 全高清&#xff08;19201080&#xff09;分辨率/30fps。 通用表达式&#xff08;适用于所有特效语言&#xff09;。 免费下载&#xff1a;https…

防火墙技术的演进,什么是下一代防火墙(NGFW)?

防火墙技术的演进 防火墙技术的演进经历了不同阶段&#xff0c;从包过滤防火墙到状态检测防火墙&#xff0c;再到集成多种安全功能的UTM&#xff08;统一威胁管理&#xff09;设备&#xff0c;最终发展到具备应用识别能力的NGFW&#xff08;下一代防火墙&#xff09;。 包过滤…

49.乐理基础-拍号的类型-单拍子、复拍子

当前写的东西&#xff0c;如果只是想要看懂乐谱的话&#xff0c;它是没什么意义的&#xff0c;就像我们要把 0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5。。。称为自然数&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5称为正整…

鸿蒙OS开发:【Stage模型应用程序包结构】

Stage模型应用程序包结构 为了让开发者能对应用程序包在不同阶段的形态更有清晰的认知&#xff0c;分别对开发态、编译态、发布态的应用程序结构展开介绍。 开发态包结构 在DevEco Studio上[创建一个项目工程]&#xff0c;并尝试创建多个不同类型的Module。根据实际工程中的…

MongoDB 推出新项目,助力企业构建生成式 AI 现代应用程序

MongoDB AI Applications Program可为组织提供战略路线图、行业专业知识及所需技术&#xff0c;加速从构思到大规模部署生成式 AI 应用程序 MongoDB (纳斯达克股票代码&#xff1a;MDB) 近日宣布推出 MongoDB AI Applications Program (MongoDB AI应用项目&#xff0c;简称&am…

使用VSCode生成代码、查询数据表

利用VSCode中百度生成 一、 1、输入内容&#xff1a;“给我生成一个student表&#xff0c;要求有id,createDate,userName,phone,age,sex,introduce的列信息,给我DDL与DML,5条信息都为中文信息&#xff0c;并且有一个userName必须等于张先生” 2、将生成的语句复制粘贴到数据库…