zoukankan      html  css  js  c++  java
  • 逆向-reverse

    c++

    1,封装

    封装:将函数写入结构体内部(但函数不占用结构体的内存空间)
    类:带有函数的结构体叫类
    底层c和c++没有区别,唯一的区别是编译器帮我们做了很多事情

    一般不用结构体作参数,因为设计大量的内存复制,所以一般传结构体指针

    2,this指针

    通常情况下,编译器会使用ecx寄存器来传递当前的this指针(在反汇编中区分c和c++的重要特点)

    3,构造函数与析构函数

    4,继承

    本质:数据的复制

    5,类成员的访问控制

    6,在堆中创建对象

    new的本质
    跟进一系列函数,最终调用HeapAlloc
    所以new的本质就是,malloc + 构造函数

    仔细观察c和c++的不同

    delete[] p 和 delete p
    前者删除所有对象,后者只销毁一个

    7,引用类型

    基本类型的引用类型

    类的引用类型

    指针的引用类型

    数组的引用类型

    引用的本质:指针

    引用与指针的区别:
    1,必须初始化,而且只能指向一个变量,从一而终
    2,对引用运算是对其指向的变量做运算,而不是对引用本身做运算
    3,引用类型是一个“弱化了的指针”

    void Plus(int& i)
    {
    	i++;
    }
    
    int main()
    {
    	int a = 1;
    	Plus(a);
    
    	system("pause");
    }
    

    常引用 void print(const Base& b1)

    8,面向对象程序设计之继承与封装

    合法但不合理的情况
    手机设计将电路板藏起来,但是提供按钮给人们使用
    子类的构造函数默认里面会call父类的无参构造函数(反汇编层面)
    当父类没有构造函数,子类里面无call
    结论:基类如果有构造函数,一定给子类提供一个无参的构造函数

    若在子类的构造函数里面想要调用父类的有参构造函数,可以这样写
    Teacher(int child,int father1,int father2):Person(father1,father2)

    main()
    { Teacher(1,2,3); }

    9,多态

    安全的做法:用父类对象的指针来指向子类对象
    不安全的做法:用子类的对象指针来指向父类的对象(编译器不通过,但是可以强制类型转换)
    多态:可以让父类指针有多种形态
    实现方法:通过虚函数实现多态性 virtual

    纯虚函数
    作用:规定子类都来提供这样一个接口
    如果基类中的函数没有任何实现的意义,那么可以定义为纯虚函数
    含有纯虚函数的类称为抽象类,不能创建对象,纯虚函数必须在子类中实现才可以使用

    10,虚表

    #include "stdafx.h"
    #include <stdlib.h>
    
    class Father
    {
    public:
    	virtual void Print()
    	{
    		printf("father
    ");
    	}
    };
    
    class Child:public Father
    {
    public:
    	void Print()
    	{
    		printf("child
    ");
    	}
    };
    
    void print(Father* f)
    {
    	f -> Print();
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	Father f1;
    	Child c1;
    	print(&f1);
    	system("pause");
    	return 0;
    }
    

    可以看到,当我们使用多态时,调用的函数与我们传入的对象有关,我们称之为间接调用

    如果在父类中不加virtual关键字,那么默认就call父类中的函数

    结论:只要使用虚函数,都是间接调用
    多态是通过间接调用实现的,没有间接调用,就没有多态
    多态 = 间接调用 + 虚表

    当没有虚函数时,类的大小就是基本类型的大小*个数,当有虚函数存在时,切无论有几个虚函数,其占用的内存空间都会加上4(虚表大小)

    观察虚表:

    在对象最开始的地方占用4个字节,里面存着虚表的地址

    11,运算符重载

    bool类型的本质等同于char类型
    本质:给运算符关联一个函数

    12,模板

    模板的本质:编译器替我们生成多份函数,比如我们需要int和char,那么编译器就会给我们生成2份代码,不同类型的各一份

    事例:函数模版和类模板

    template <class T>
    void Sort(T* arr,int len)
    {}
    int main()
    {
    char arr[] = "123",b = 2;
    Sort(arr,b);
    }
    
    template <class T,class M>
    class A
    {
    T a1;   M a2;
    };
    int main() { A<int,char>  obj;}
    

    13,纯虚函数

    语法:
    virtual int max() = 0;

    含有纯虚函数的类,称为抽象类,抽象类也可以包含普通的函数
    抽象类不能实例化

    作用:抽象类看成是一个任何该类的子类都必须遵守的标准
    (比如淘宝店都有相同的功能模块,但是内容各不相同,所以可以用一个抽象类来作一个标准,真正实现的是在子类中)

    14,对象拷贝—拷贝构造函数

    如果不需要深拷贝,不要自己添加拷贝构造函数
    父类也会拷贝
    本质:内存的复制

    15,对象拷贝—重载赋值运算符

    16,友元

    垃圾语法,破坏了c++的封装特性,不建议使用
    (为什么有呢?是向面向过程的妥协,先有c语言再有c++,之前程序员写了很多代码,但是有了c++之后,不加友元有些类的private的成员就不能访问了,是一种妥协)
    在之后的面向对象中(java,c#)就没有友元这个东西了

    17,内部类

    在别的类里面定义的类叫做内部类
    在内存上毫无关系,在权限上也毫无关系
    总结:内部类和它外面的类毫无关系

    作用:要想创建内部类必须写完整的名字而且内部类得在public权限里面

    outer::inner obj;
    

    内部类存在的唯一价值:外类的某个函数会用到内部类,就把内部类定义到private权限里面就可以了,别的类不需要用,完美体现了封装隐藏的特性
    如果只有一个函数需要这个类,甚至可以将一个类定义到一个函数里面,当使用这个函数时这个类才有价值

    18,命名空间

    作用:解决命名冲突的问题
    命名冲突问题
    终极解决方案:命名空间

    namespace name1{
    1,全局变量
    2,函数
    3,类
    }

    不同命名空间里面的内容可以完全一样
    访问的时候这样写

    ns1::x
    ns1::func()
    ns1::Cobj obj;
    

    本质:给名字起个前缀

    19,static关键字

    static修饰局部变量,作用:私有的全局变量(只能当前函数使用)

  • 相关阅读:
    【python】raise_for_status()抛出requests.HTTPError错误
    【python】python打包生成的exe文件运行时提示缺少模块
    单点登录原理与简单实现
    Java并发之AQS详解
    Java更新
    各种java面经资源
    HashMap与HashTable的区别
    Http 与Https
    SpringMVC运行原理
    Spring
  • 原文地址:https://www.cnblogs.com/lemon629/p/13911774.html
Copyright © 2011-2022 走看看