0%

重载

对已有的运算符赋予多重含义,使得同一运算符作用于不同数据类型的数据时导致不同类型的行为。
形式:
返回值类型 operator 运算符(形参表){}
注意,当重载为成员函数时,参数个数为运算符数目-1.
例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Complex{
public:
double real,imag;
Complex(double r = 0.0,double i = 0.0):real(r),imag(i){}
Complex operator-(const Complex &c);//声明重载为成员函数
};
Complex operator+(const Complex &a,const Complex &b)
{
return Complex(a.real+b.real,a.imag+b.imag);//返回临时对象
}
Complex Complex::operator+(const Complex &c)
{
return Complex(real-c.real,imag-c.imag);//只需一个参数,a-b相当于a.operator-(b)
}

调用时:
在这里插入图片描述

  • 赋值运算符重载
    它只能重载为成员函数
    简单用法如下:在这里插入图片描述
    问题:
    1
    2
    3
    String s1,s2;
    s1="this";s2="that";
    s1=s2;
    使用原生的赋值运算符,可以吗?答案是no。
    看一下会出现的问题:
    在这里插入图片描述
  1. this的空间失去了指针指向它,没有被delete就废弃了,产生内存垃圾。
  2. 如果s1消亡,析构函数会delete s1所指向的内存空间。s2也就无所指了。当s2消亡,再一次析构delete已经删除的空间,程序崩溃。
    这里如果再令S2=”other”;S1指向仍是that。因为S2=”other”,是将S2指向other所在的内存地址,而不是修改S2已经指向的地址单元的值。
    解决方法:
    在这里插入图片描述
  • 流插入和流提取运算符重载
    cout是ostream类的对象,cin是istream类的对象。这两个类均定义在iostream中。
    在类中分别对<<和>>进行了重载。
    针对输出/输入的不同类型,c++重载了多个成员函数。
    比如输出int:

    1
    2
    3
    4
    void ostream::operator<<(int n){
    ......//输出n的代码
    return;
    }

    当我们想要输出特定的格式的数据时,比如复数,简单的调用cout<<输出对象肯定就不行了。自己根据需要重载<<流插入和>>流提取运算符。下面以输入输出复数类举例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    int main(){
    Complex c;//Complex为复数类
    int n;
    cin>>c>>n;
    cout<<c<<",";
    return 0;
    }

    class Complex{
    double real,imag;
    public:
    Complex(double r = 0,double i = 0):real(r),imag(i){};//构造函数
    friend ostream& operator<<(ostream& os,const Complex& c);//全局函数,并声明为友元。返回值需要是ostream类的引用,即cout方便连续调用。
    friend istream& opeator>>(istream& is,Complex& c);
    }

    ostream& operator<<(ostream& os,const Complex& c){
    os<<c.real<<"+"<<c.imag<<"i";//输出以a+bi的形式
    return os;
    }
    流提取运算符的重载类似,做一些字符串分割处理即可。注意接收键盘输入,不能为const
  • 类型转换运算符的重载不需要写返回值

  • 自增和自减运算符的重载
    前置运算符作为一元运算符重载
    后置运算符作为二元运算符重载,多写一个没用的参数
    例子:要实现下面的输出,该如何重载?在这里插入图片描述

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    class CDemo{
    private: int n;
    public:
    CDemo(int i = 0):n(i){}
    CDemo& operator++();//前置
    CDemo operator++(int);
    //后置,多一个无用参数。c++中,后置运算符没有返回引用,只是返回临时对象。
    //因此i++ = 1这种写法是禁止的
    //而++i返回i的引用,可以++i = x;这样的i就是x
    operator int(){return n;}//重载类型转换运算符
    friend CDemo& operator--(CDemo&);//声明友元,--用全局重载
    friend CDemo& operator--(CDemo&,int);//后置
    };
    CDemo& CDemo::operator++()//前置++
    {
    ++n;
    return *this
    }
    CDemo CDemo::operator++(int){//后置++
    CDemo temp(*this);
    n++;
    return temp;//返回修改前的对象,实际上n变化了。
    }
    CDemo operator--(CDemo& d){//前置--
    d.n--;
    return d;
    }
    CDemo operator--(CDemo& d,int){//后置--
    CDemo temp(d);
    d.n--;
    return temp;
    }

最后再补充一点重载的注意事项
在这里插入图片描述

1.复制构造函数

形如X::X(X&)或X:X(const X&)的构造函数。它只能有一个参数,即同类对象的引用。
如果没有自己定义,系统生成默认的复制构造函数,完成复制功能。

它仅在下面三种情况下起作用:

  1. 当用一个对象去初始化同类的另一个对象
    1
    2
    Complex c2(c1);
    Complex c2 = c1;
  2. 某个函数有参数是类A的对象,则该函数被调用时,类A的复制构造函数也被调用。
    1
    2
    3
    4
    5
    6
    void Func(A a1){}
    int main(){
    A a2;
    Func(a2);
    return 0;
    }
  3. 函数返回值是类A的对象,函数返回时,A的复制构造函数被调用。
    1
    2
    3
    4
    5
    A func(){
    A b(4);
    return b; //返回了A的对象
    }
    int main(){Func();}//此时类A的复制构造函数也会被调用。

2.类型转换构造函数

话不多说,直接上例子
在这里插入图片描述
c1 = 9,其就相当于 c1 = Complex(9);

3.静态成员函数/变量

实际上就是全局函数和变量。设计这一概念主要为了增强某些变量与类的关联性。
静态成员函数并不具体作用与某个对象。静态成员变量占一份地址,为所有对象共享。

1
2
3
4
5
6
7
8
class A{
private:
int x,y;
static int totalX;
static int totalY;
public:
static void printTotal();
}

记住一点,sizeof运算符不会计算静态的成员变量。

4. 友元函数/类

1.友元函数

1
2
3
4
5
6
7
8
9
10
11
class A{
public:
void aFunc(B* b);
};
class B{
private:
int p;
friend int bFunc(int x);//全局函数
friend void A::aFunc(B *b);//在class B中声明友元,bFunc和aFunc都可以访问classB的私有成员
一个类的友元函数可以访问该类的私有成员
}

2.友元类

1
2
3
4
5
6
7
8
9
10
11
class A{
private:
int p;
friend class B;//声明B是它的友元类
}
class B{
public:
A a;
void funcB(){
a.p+=100;//B是A的友元类,所以B中的成员函数可以访问A的私有成员
}

注意:

  1. 声明友元,在被当做友元的类中声明,即我宣布谁是我的朋友。
  2. 友元关系不能传递和继承。

最近博主无聊的开始想打打ctf,开个博客记录一下。。

博主平时做前端开发做的比较多,ctf这边就打打web了。

1.按不下去的按钮和复制不了的文字

按钮按不了,控制台获取这个input对象设置其disabled为false,点击就可以。
在这里插入图片描述
这题本意是用document.oncontextmenu=true设置右键可用,按下f12其实就好了。。
在这里插入图片描述

2.robots协议

robots.txt文件是一个文本文件,使用任何一个常见的文本编辑器,就可以创建和编辑它 。robots.txt是一个协议,而不是一个命令。robots.txt是搜索引擎中访问网站的时候要查看的第一个文件。robots.txt文件告诉爬虫程序在服务器上什么文件是可以被查看的。
当一个搜索爬虫访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索爬虫将能够访问网站上所有没有被口令保护的页面。
协议显示禁止抓取这个php文件,输入框直接访问该文件可得到flag。

在这里插入图片描述
robots协议文件写法举例:
在这里插入图片描述

3.简单的密码爆破

不知道密码,用户名为admin。用burp抓包暴力破解。
在这里插入图片描述
用网上下载的字典进行爆破,发现当密码为123456时,返回的数据长度不一样。查看response即可发现flag。
在这里插入图片描述

暂时先更到这里了。。作简单的记录用,感觉这一块比码代码有意思多了,哈哈

1.数据类型

  1. == 和 ===的区别:
    两个=判断相等,类型不等值相等也会判断为true。如 “1”和1
    三个=则是绝对相等

  2. 判断是否为数字(NAN),不能使用NAN===NAN,需要使用isNAN()判断。
    var a = 5 ; isNAN(a)

  3. 数组
    定义:var array=[1,2,3,'hello',null]
    或是 new Array(1,2,3,'hello',null)
    取数组时,如果下标越界只会显示undefined。

    数组的长度是可以通过赋值改变的,如果赋的过小会导致元素丢失。

    1
    array.length=2; //导致下标大于1的元素丢失

    截取数组部分元素的方法.slice()

    1
    array.slice(1,4) //截取第二个到第四个,留头去尾

    数组中元素的操作

    1
    2
    3
    4
    5
    6
    7
    8
    array.push('x') //向数组尾部压入元素x
    array.pop() //数组尾部弹出一个元素
    array.unshift('x') //在头部压入元素x
    array.shift() //在头部弹出
    array.sort() //排序数组
    array.reverse() //反序数组
    array.concat([1,2,3]) //拼接数组,不修改原数组,返回新的数组
    array.join('-') //以指定字符连接数组中的元素
  4. 对象
    若干个键值对。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var person = {
    name:"mike",
    age:18,
    tags:['js','html','flutter']
    }
    person.name //取对象
    delete person.age //删除对象中的属性
    'age' in person //判断属性是否在对象中
    person.hasOwnProperty('toString) //判断是否是自己定义的属性
  5. var 和 let
    let用于声明局部变量,所声明变量只在let命令所在代码块内有效。
    var声明的变量是全局的。
    使用use strict在js中设置严格检查模式。

  6. 1 变量提升

    1
    2
    3
    4
    5
    var v='Hello World';
    (function(){
    alert(v);
    var v='I love you';
    })()

    为什么输出会是undefined?这就要提到js中的变量提升机制了。在定义var v = 'I love you'时,实际上js把变量v提到了函数的top地方。也就是说,在function的第一行其实是存在一个隐形的定义 var v;的。
    let定义的变量不存在变量提升机制,且不允许重复声明。

  7. 字符串
    定义 var a = '123' 或是 var a ="123"
    转义字符\n \tab \'等,反斜杠后跟转义字符。
    多行字符串使用``包裹。
    模板字符串let msg = 'hello,${name}' name是另外的变量。
    一些字符串操作函数:

    1
    2
    3
    4
    5
    str.length //获取字符串的长度
    str.toUpperCase() //转换成大写
    str.toLowerCase() //转换成小写
    str.indexOf('e') //获取某个元素在数组的下标
    str.subString(1,3) //截取第二到第四个字符串
  8. Set和Map
    Set和Map是ES6中新增的数据结构。Set为无序不重复的数组,Map本质上是一组键值对的集合。

    1
    2
    3
    4
    5
    6
    7
    var map = new Map(['name','huijunyu'],['age',19])
    var name = map.get('name') //根据key拿value
    map.set('age',20) //设置value
    map.delete('name') //删除指定key
    map.keys() map.values() map.entries
    map.has("key") //判断Map中是否有某个key对应value
    map.clear() //清空map对象的内容
  9. Loop循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for i in array{
    console.log(array[i]) //i为索引值
    }
    for i of array{
    console.log(i) //i为属性值
    }
    const numbers = [45, 4, 9, 16, 25];
    let txt = "";
    numbers.forEach(myFunction); //forEach方法为每个数组元素调用一次函数
    function myFunction(value) {
    txt += value;
    }

    2.函数

  10. 定义函数
    function f1(x){}
    var f1 = function(x){}

  11. arguments rest 关键字
    arguments包含了所有的参数,是一个数组。js的函数在接收参数时可以接收任意个,使用arguments可以进行全部参数的访问。
    rest可以获取除了定义要接收的参数以外的其他参数。形式如下
    function f1(a,b,...rest){}
    rest同样是一个数组。

  12. apply函数
    js中,apply函数可以改变this指针的指向。

    1
    2
    3
    4
    5
    6
    function f1(){
    return this.name} //有点怪异,让它返回名字。本来的this是windows,找不到name。
    var classA = {
    name:'hjy',
    age:f1};
    f1.apply(classA,[]); //this指针指向了classA
  13. json对象
    JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它是一个格式化的字符串,可以和js对象相互转化。

    1
    2
    3
    4
    5
    6
    7
    var user = {
    name:'hjy',
    age:18,
    sex:'男'
    }
    var jsonUser = JSON.stringify(user); //js对象转json字符串
    var obj = JSON.parse('{"name":"hjy","age":18,"sex":"男"}') //json字符串转js对象

    要注意json和js对象的区别!

    3、BOM和DOM

    BOM

  14. window 代表浏览器窗口
    window.alert
    window.innerHeight等属性和方法

  15. Navigatot 封装了浏览器的信息
    navigator.platform
    navigator.appName Navigator可能会被人为修改,不建议用之中的属性判断和编写code

  16. screen 代表屏幕
    screen.width screen.height

  17. location 代表当前页面的URL信息
    location.host location.reload()
    location.assign('url') //设置新的地址

  18. history 获取浏览器的历史记录
    history.forward() history.back()

DOM

浏览器实际上就是一个DOM树,我们需要对它其中的一个个div,各种元素进行操作。

  1. 获取DOM节点
    document.getElementById('id') //最常用的
    document.getElementByClassName('class')
    document.getElementByTagName('tag')

  2. 操作DOM节点
    var a = document.getElementById('id') a.innerText='text' a.innerHTML='<strong>text</strong>'
    innerHTML可以识别HTML标签
    a.style.color='yellow'
    还可以操作节点的css属性

  3. 删除DOM结点
    不能直接删除,要获取父节点,通过父节点删除

    1
    2
    3
    var self = document.getElementById('p1');
    var father = p1.parentElement;
    father.removeChild(self)
  4. 创建DOM节点

    1
    2
    3
    4
    var newP = document.createElement('p') //创建一个p标签 
    newP.setAttribute('id','newP')
    newP.setAttribute('innerText','Hello World')
    list.append(newP) //插入DOM结点

    更多DOM操作详见W3C js Document

什么是工厂模式?就是将本该创建的产品委托给一个个的工厂(factory)去创建。在工厂里对对象进行修改,解除耦合。

1.简单工厂模式

由工厂类,产品接口和具体产品三部分组成。
简单工厂例子-咖啡生产
在工厂类中,定义createCoffee的方法,返回一个Coffee类型的对象。在方法中通过传入参数type的if判断来创建不同的咖啡子类,如美式,拿铁…
在store类中,只需要创建相应的简单工厂类的对象:
SimpleCoffeeFactory factory = new SimpleCoffeFactory(); Coffee coffee = factory.createCoffee(type);
返回的coffee即为需要制作的各种咖啡。

简单工厂模式违反了开闭原则。当需要增加新的咖啡种类时,需要修改简单工厂类中的代码(if…)

2.工厂方法模式

为了解决简单工厂模式带来的问题——违反了开闭原则
定义一个用于创建对象的接口,让其子类决定实例化哪个产品对象。它包括 抽象工厂 具体工厂 抽象产品以及具体产品。
在这里插入图片描述
在调用时:
CoffeeFactory factory = new AmericanCoffeeFactory(); Coffee coffee = factory.createCoffee();
用户只需要知道具体的工厂名称即可。无需知道产品如何生产(隐藏在具体工厂中)。
满足开闭原则。
但是每增加一个产品就需要增加一个具体产品类和一个对应的具体工厂类,增加了复杂度。

3.抽象工厂模式

当需要生产多层次多级别的产品?需要一个 综合性 的工厂。
在这里插入图片描述
美式:美式咖啡和抹茶慕斯
意大利:提拉米苏和拿铁咖啡
如何调用?
ItalyDessertFactory factory = new ItalyDessertFactory(); Coffee coffee = factory.createCoffee(); Dessert dessert = factory.createDessert();
由意大利工厂生产出来的咖啡和甜品是拿铁和提拉米苏。

能让客户始终使用同一产品族的对象。
但是当产品族中添加产品(如添加:小食)时,所有的工厂都要改变。符合开闭原则?视情况讨论咯。

1.在csdn博客上或者是其他平台上用md格式编写你的文章。当然,直接使用markdown工具在本地编写也是可以的。就像这样
2.将生成的md文件放到source下的_posts文件夹中

在这里插入图片描述

3.在你存放博客的blog文件夹目录下右击调出git,执行hexo g(generate)进行静态部署,然后输入hexo s(server)启动本地服务器,用于预览文章。最后执行hexo d(deploy)生成网页的静态文件,并部署到指定仓库。这样,一个博客就成功发布到你的网站上啦!

SpringBoot框架的基本结构

1.总框架预览

工程大部分代码存放于src文件夹中,与之同级的有maven的配置文件pom.xml。src中有java和resource两个主要文件夹,java文件夹中存放的是springboot项目的主要代码部分,resource中存放的是项目的一些配置信息,如application.yml。
在这里插入图片描述

2.java模块中的各层代码详解
①controller层

controller的概念在mvc中就已经存在,一般指控制部分。对view层提交的请求设置对应的servelet进行特定处理。
在这里插入图片描述

②entity层

entity层是实体类层,一般与所连接的数据库中每个表对应。需要注意同时应该生成getter setter方法和构造方法。

③mapper层

mapper层中定义的是对数据库的操作,一般表现为接口形式。在这里插入图片描述

④service层

应用服务层,在其中创建mapper对象来进行进一步的包装。在项目结构不是十分复杂的情况下,是可有可无的。
在这里插入图片描述

配置一个flutter项目

第一步 安装java的jdk
第二步 安装Android Studio
第三步 安装flutter的sdk

将flutter的bin目录配置到Path环境变量中。

第四步 打开Android Studio,安装flutter插件
第五步 在Android Studio中创建一个flutter项目,并在vscode中安装dart和flutter插件,在vscode中打开flutter文件。

在这里插入图片描述

1.new GestureDetector()

利用GestureDetector中的ontap()事件进行文本点击响应。

1
2
3
4
5
6
7
8
9
10
child: GestureDetector(
child: Text(
this.title,
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
onTap: this.rightClick,
),
rightClick: () {
print("点我干什么");
},
2.TextSpan()部件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: "hello",
style: TextStyle(fontSize: 29, color: Colors.red),
),
TextSpan(
text: "world",
style: TextStyle(fontSize: 59, color: Colors.yellow),
// 设置点击事件
recognizer: TapGestureRecognizer()
..onTap = () {
debugPrint("${i++}");
},
),
],
),
3.Listener监听触摸事件
属性 说明
onPointerDown 按下时触发
onPointerMove 移动时触发
onPointerEnter 进入Widget区域时触发
onPointerExit 离开Widget区域时触发
onPointerUp 离开屏幕时触发
onPointerCancel 取消触摸时触发
behavior 控制事件传递