首页 > 编程语言 >C++逆向分析——友元、内部类、命名空间和static

C++逆向分析——友元、内部类、命名空间和static

时间:2023-04-09 11:12:44浏览次数:36  
标签:友元 函数 C++ static CObject Test

友元

友元可以理解为:朋友、元素;老师认为这个友元是C++中的一个垃圾,因为友元的存在破坏了面向对象的封装性,不推荐使用,之所以有这个章节是因为有人不了解这个概念

注意:在一些新版本的C++编译器里面已经不再提供类似于友元这样的特性了。

大家都知道在C++中对象的私有成员,外部是无法访问的,这在面向对象中是很正常的,如果你想访问按照正常的逻辑你应该在类中声明成员函数去增删改查这个私有成员。

images/download/attachments/12714553/image2021-4-18_21-54-57.png

友元的诞生就是破坏了这个封装性,让你可以在外部去使用这个私有成员。

images/download/attachments/12714553/image2021-4-18_21-56-54.png

友元的语法就是:friend 返回类型 函数名(参数列表)

老师个人认为C++之所以有友元是因为这是C++作者面向过程的一种妥协,这是因为C++是先有的C才有的C++,而很多人已经很熟悉C语言的语法了,你这时候推出一个新的概念,是对开发者的不友好(代码重构、学习代码),所以要妥协。

刚刚举例说明的是友元函数,就是告诉编译器这个函数是我的朋友,可以访问我的任何成员。

除了友元函数,还有加强版的垃圾:友元类,如下是语法格式:

class CObject { friend class Test; private: int x; public: CObject() {} CObject(int x) { this->x = x; } };   class Test { public: void Fun(CObject* c) { printf("%d \n", c->x); } };

以上代码就是告诉编译器,Test是CObject的朋友,所以Test可以直接访问CObject的私有成员;但是要注意的是,这种访问是单向的,Test可以访问CObject,但反之则不行。

内部类

内部类,简单的说就是在别的类里面定义的类就是内部类。

  • 大小:当前类和其内部类不存在包含关系,不会影响当前类的大小;

images/download/attachments/12714553/image2021-4-18_22-12-59.png

  • 关系:两者之间不存在什么特殊关系,也无法访问对方的私有成员;

images/download/attachments/12714553/image2021-4-18_22-14-8.png

  • 声明:声明创建内部类需要使用格式 → 类::内部类 名称;

  • 权限:如果你的内部类不想外部创建对象,那就定义到private内即可;而如果你用到这个内部类的情况非常的少,例如你只有一个成员函数需要使用到,那么完全可以定义到这个函数内;

  • 作用:如果我们需要实现一些功能而用到一个类,但是其他的模块、类用不到,我们可以就把这个类写到当前所需要使用类中。(隐藏

命名空间

命名空间主要是用来解决命名冲突的问题;比如你定义了一个函数叫Fun,而如果你还想定一个函数也叫Fn,这种情况下就可以使用命名空间来解决这个问题。

命名空间的关键词:namespace,其语法格式如下:

namespace 名称x { // 全局变量 // 函数 // 类 }   namespace 名称y { // 全局变量 // 函数 // 类 }

images/download/attachments/12714553/image2021-4-18_22-29-34.png

调用也很简单,使用格式:命名空间名称::函数\变量\类

如果我们命名空间内的东西非常多,但是你要调用就必须要加上前缀,这时候你可以在代码的首行写:

using namespace x;

但这也会引起命名冲突,如果命名空间x里面有一个Test函数,但是在正常代码中也存在Test函数,你想调用的是本身的该怎么办呢?实际上在C++中,你定义的所有东西都存在一个全局命名空间,而想调用可以使用如下语法:

::Test();

static关键字

用static就是一个全局变量,只不过它是一个私有的全局变量。

在面向过程(没有对象的概念,用函数)中的static:

void Func() { static char strBuffer[0x10]; strcpy(strBuffer, "test"); }

用static声明的全局变量,只有当前函数能访问;我们可以看下反汇编代码来论证这是一个全局变量:

images/download/attachments/12714553/image2021-4-18_23-7-0.png

如上图所示的这个内存地址,很明显就是一个全局区的地址(这也就表示相同变量只能申请一次,不再接受第二次申请,也就表示全局变量应用场景,你可以用这个关键词来实现)。

面向对象设计中的static之静态数据成员:

images/download/attachments/12714553/image2021-4-18_23-12-45.png

面向对象设计中的static之静态成员函数:

images/download/attachments/12714553/image2021-4-18_23-23-52.png

static的经典应用:单子模式;有些时候我们希望定义的类只能有一个对象存在,这时候你该如何限制呢?实现思路有两个:

  1. 禁止对象被随便创建

  2. 保证对象只有一个存在

images/download/attachments/12714553/image2021-4-18_23-30-12.png

标签:友元,函数,C++,static,CObject,Test
From: https://www.cnblogs.com/bonelee/p/17300013.html

相关文章

  • C++逆向分析——运算符重载
    运算符重载现在有一个类,其中有一个函数用于比较2个类的成员大小:#include<stdio.h> classNumber{private:intx;inty;public:Number(intx,inty){this->x=x;this->y=y;}intMax(Number&n){returnthis->x>n.x&&this->y>n.......
  • C++逆向分析——模版
    模版假设有一个冒泡排序的函数:voidSort(int*arr,intnLength){inti,k;for(i=0;i<nLength;i++){for(k=0;k<nLength-1-i;k++){if(arr[k]>arr[k+1]){inttemp=arr[k];arr[k]=arr[k+1];arr[k+1]=temp;}}}}但是这个冒泡......
  • C++逆向分析——构造函数和析构函数
    构造函数与析构函数构造函数structStudent{inta;intb; Student(){printf("Look.");} voidInit(inta,intb){this->a=a;this->b=b;} };如上代码中,我们发现了存在一个函数,这个函数没有返回类型并且与结构体名称一样,那这段函数在什么......
  • Code-C++ Invoke Python
    Code-C++InvokePythonhttps://www.cnblogs.com/yongchao/p/17299892.html使用C或C++扩展Python扩展和嵌入Python解释器Python3.10.11Python/CAPI参考手册Python3.11.3Python/CAPI参考手册https://www.cnblogs.com/lidabo/p/17043302.htmlhttps://bl......
  • C++逆向分析——继承
    继承structPerson{intage;intsex;}; structTeacher{intage;intsex;intlevel;intclassId;};如上代码中可以看见,Teacher类与Person类都存在着相同的2个成员age和sex,那么这就相当于重复编写了,我们可以通过继承的方式避免这样重复的编写(当前类名称:......
  • C++逆向分析——new和delete new[]和delete[]
    在堆中创建对象我们可以在什么地方创建对象?全局变量区,在函数外面在栈中创建对象,也就是函数内在堆中创建对象注意:之前一直提到的堆栈实际上是两个概念->堆、栈,我们之前所讲的就是栈,从本章开始要严格区分。在C语言中,我们可以通过一个函数去申请一块内存,就是malloc(N)......
  • C++逆向分析——类成员的访问控制
    类成员的访问控制课外→好的编程习惯:定义与实现分开写,提升代码可读性。如下代码,Student这个类的所有成员我们都可以调用,但是我们不想让被人调用Print1这个方法该怎么?structStudent{intage;intsex; voidPrint1(){printf("FuncPrint1");} voidPrint......
  • C++逆向分析——引用
    引用类型引用类型就是变量的别名,其在初始化时必须要赋值。//基本类型intx=1;int&ref=x;ref=2;printf("%d\n",ref); //类Personp;Person&ref=p;ref.x=10;printf("%d\n",p.x); //指针类型int******x=(int******)1;int******&ref=x;r......
  • C++逆向分析——继承与封装
    面向对象程序设计之继承与封装之前已经学习过继承和封装了,但是要在实际开发中使用,光学语法和原理是不够的,在设计层面我们需要做一些优化。如下代码是继承的例子:#include<stdio.h> classPerson{public:intAge;intSex; voidWork(){printf("Person:Work()......
  • C++逆向分析——多态和虚表
    虚表上一章了解了多态,那么我们来了解一下多态在C++中是如何实现的。了解本质,那就通过反汇编代码去看就行了,首先我们看下非多态的情况下的反汇编代码:然后再来看下多态情况下的反汇编代码:很明显这里多态的情况下会根据edx间接调用,而非多态则会直接调用。那么我们来看下间接......