【C++】类和对象---需掌握的功能

news/2024/5/6 16:47:51/文章来源:https://blog.csdn.net/m0_52094687/article/details/129001408

目录

  • 1.初始化列表
    • 1.1构造函数赋值
    • 1.2初始化列表
      • 格式:
      • 编译器执行的顺序:
      • 特性:
    • 1.3explicit关键字
      • 类型替换过程
      • 多参数构造函数类型替换(C++11)
  • 2.static成员
    • 编程题
  • 3.匿名对象
  • 4.友元
    • 4.1友元函数
    • 4.2友元类
  • 5.内部类
  • 6.拷贝对象时的一些编译器优化
    • 6.1传值传参
    • 6.2传值返回
  • 7.理解类和对象

1.初始化列表

1.1构造函数赋值

创建对象时,编译器会调用构造函数来为对象中的成员变量一个合适的初始值。

但不是所有的成员变量都可以在构造函数内获得初始值的,如下代码:

在这里插入图片描述
运行后给出如下错误

在这里插入图片描述

这是因为被const修饰的变量只能在定义的时候初始化,那哪里是成员变量定义的地方?

答:成员变量在初始化列表 中定义并初始化。

如下图,是我们经常写的类:

在这里插入图片描述
在类内private访问限定符下的成员变量只是成员变量的声明 ,在对象创建时(也叫定义对象)会调用类内的构造函数(默认构造函数或非默认构造函数),其中在 成员变量的定义 的位置,也叫做初始化列表 (下面会讲,现在知道这个位置即可),成员变量在这个地方定义的,如果成员变量中有被const修饰的可以在此处初始化。

了解了这些,我们在来看一下初始化列表的具体特性和功能。

1.2初始化列表

格式:

初始化列表:在构造函数(默认构造函数或非默认构造函数)下以一个冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个“成员变量 ”后面跟一个放在括号中的初始值或表达式

class Date
{
public:Date():_year(1),_month(1),_day(1){}
private:int _year;int _month;int _day;
};

编译器执行的顺序:

  1. 之所以在这个位置以该格式写的代码被称为初始化列表,一是因为在这里成员变量完成定义,其次是编译器在对象创建后调用构造函数也是先执行初始化列表 ,将对应的成员变量初始化后,在执行构造函数体内的代码

    如下图:

    在这里插入图片描述

  2. 如果我们没有实现初始化链表,编译器会默认实现,因为对于成员变量必须要定义,而初始化列表就是定义成员变量的,只是这样初始化后的成员变量值为随机值,需要看它的构造函数或其他函数是否为其赋值。

    但要注意,我们没有实现初始化列表,遇到被const修饰的成员函数或其他特殊的情况(下面会讲),可就运行不了了。

    结论: 尽量使用初始化列表。

  3. 成员变量 在类中声明次序 就是其初始化列表中的初始化顺序 ,与其在初始化列表中的先后次序无关。

    如下图,调换初始化列表的顺序,可以观察到,程序的执行顺序为_year_month_day与声明顺序相同。

    在这里插入图片描述

特性:

  1. 每个成员变量在初始化列表中只能出现一次

    初始化只能初始化一次,第二次就成复制了,赋值是在构造函数体内完成。

  2. 类中如果包含以下成员,必须放在初始化列表位置处初始化。

    • 引用成员变量

      引用的特点就是在定义时必须赋值。

    • const成员变量

      被const修饰的变量,如果不在定义时初始化,其他时候无法改变它的值,那该变量的存在就没有价值。

    • 自定义类型成员(且该类中没有默认构造函数时)

      没有默认构造函数,意味着有非默认构造函数,编译器无法在其定义时自动初始化该成员变量,只能通过我们自己传值调用其非默认构造函数。

    class A
    {
    public:A(int a): _a(a){}
    private:int _a;
    };class B
    {
    public:B(int a, int ref): _Aobj(a), _ref(ref), _n(1){}
    private:A _Aobj;        //没有默认构造函数int& _ref;      //引用const int _n;   //const
    };
    
  3. 注意: 尽量使用初始化列表,如果不能用初始化列表初始化的成员变量,如需要开辟空间的情况等等,在构造函数体内完成即可,不要只盯着初始化列表。

拓展:

C++11中规定内置类型成员变量在类中声明时可以给默认值。

这里的默认值是缺省值,不是初始化,比方说对于被const修饰的成员变量,如果在声明时给出默认值,并在初始化列表初始化,最后以初始化列表为主,若是初始化列表没有初始化则以默认值为主

class Date
{
public:Date(): _year(1){cout << _year << endl;}
private:const int _year;int _month;int _day;
};
class A
{
public:A(){cout << _year << endl;}
private:const int _year = 2;
};int main()
{Date today;A a;return 0;
}

在这里插入图片描述

1.3explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数(统称:单参数默认构造函数),还具有类型替换的作用。

若不想实现这种功能,在构造函数前增加关键字explicit即可

在这里插入图片描述

类型替换过程

接下来我们一步步探索这个现象

我们先来看如下代码

int main()
{int a = 1;double b = a; //隐式类型转化return 0;
}

这个代码是可以运行成功的,变量a在为b赋值时,发生隐式类型转化,首先生成了一个const double类型的临时变量(临时变量有常性 ),变量a将值赋给这个临时变量,由临时变量将值赋给变量b

在这里插入图片描述

了解了临时变量的存在,在来看下面的一段代码

class A
{
public:A(int a): _a(a){cout << "A(int a)" << endl;}private:int _a;
};int main()
{const A& b = 1;return 0;
}

在这里插入图片描述

我们看到,代码成功运行并输出,而想要为引用初始化,需要为其赋一个同类型的变量,所以const A& b = 1;中,先创建一个临时的A类型对象(临时的对象也有常性,所以引用需要使用const修饰),并使用1为其成员变量赋值,这个过程调用构造函数,接着使对象b成为零时对象的引用,证明这么做必然会产生一个临时的变量。

在这里插入图片描述

到这里类型替换的过程也就呼之欲出了,不过结果可能和大家想象的不一样。

看如下代码

class A
{
public:A(int a): _a(a){cout << "A(int a)" << endl;}A(const A& aa): _a(aa._a){cout << "A(const A& a)" << endl;}
private:int _a;
};int main()
{A a = 1;//等价于: A a(1);return 0;
}

在这里插入图片描述

按照正常的想法,通过构造函数创建一个临时对象,在通过拷贝构造函数创建对象a,而现在只调用了构造函数,这是为什么?

这是编译器帮我们做出的优化,正常的过程是构造->拷贝 = a,但C++觉得这么做有些繁琐,便取消了拷贝的过程,直接通过1来构造对象a ,等价于A a(1)

在这里插入图片描述

  • 在C++发展之初这些优化是没有的,但随着发展,编译器不断进化,开始减少很多没必要的步骤,慢慢做出优化,同时对语法的要求更高,保证优化后对编译没有影响。
  • 一般新一点的编译器会有优化,老的编译器没有。

多参数构造函数类型替换(C++11)

对于多参数的构造函数,C++98是不支持进行类型替换的,但在C++11对这一块进行拓展,支持其多参数进行这一操作。需在进行多参数替换时,使用大括号包含需要传的参数即可。如下

在这里插入图片描述

  • 注意:若不想进行替换操作,在构造函数前增加explicit关键字即可

2.static成员

声明为static的类成员 称为 类的静态成员 ,用static 修饰的 成员变量 ,称之为 静态成员变量 ;用 static修饰成员函数 ,称之为 静态成员函数静态成员变量一定要在类外进行初始化。

其特性如下:

  1. 静态成员所有类对象共享 ,不属于某个具体的对象,存放在静态区
  2. 静态成员变量 必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数 没有 隐藏的 this指针,不能访问非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

了解了特性我们需要注意以下几种情况:

  1. 创建类的指针对象,设置为空,它可以访问类中的静态成员和静态函数

    class A
    {
    public:static void Print(){cout << _a << endl;}
    private:static int _a;
    };int A::_a = 0;int main()
    {A* a = nullptr;a->Print();return 0;
    }
    

    在这里插入图片描述

    静态成员为所有类对象共享,使用空指针调用,不涉及指针自生,甚至在静态成员函数内不会有this指针,不会造成编译错误。

  2. 静态成员函数不能调用非静态成员函数

    静态成员函数内没有this指针,无法调用除静态成员外的其他成员

  3. 非静态成员函数可以调用类的静态成员函数

    静态成员是所有类对象共享,所有对象都可以调用,非静态成员内有this指针,为类对象指针,可以调用静态成员,甚至非成员函数,普通函数或其他类的成员函数都可以通过类名::静态成员的方法调用一个类的静态成员

了解了这些,我们使用静态成员来做一道编程题:

编程题

求1+2+3+…+n_

描述:

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句

(A?B:C)。

数据范围: 0<<n≤200
进阶: 空间复杂度 O(1) ,时间复杂度 O(n)

示例1

输入: 5

返回值:15

示例2

输入:1

返回值:1

思路:

我们创建一个类,设置两个静态成员变量,一个sum存放所有数相加的和,一个i表示当前需要加几,编写其构造函数,使创建一次对象sum加一次i,同时使i自加1,之后创建n个这个类的对象,最后得到的sum就是总和,因为成员变量一般放在private限定符下,所以在通过创建一个静态成员函数来返回这个静态成员变量sum。

注意: 创建n个对象可以使用变长数组 类名 arr[n]new,变长数组是c99中定义的,是否可以使用取决于编译器是否支持,在牛客网中的编译器支持这一语法。

代码:

class Sum
{
public:Sum(){_sum += _i;_i++;}static int Print(){return _sum;}
private:static int _sum;static int _i;
};int Sum::_sum = 0;
int Sum::_i = 1;class Solution {
public:int Sum_Solution(int n) {Sum arr[n];return Sum::Print();}
};

3.匿名对象

我们创建对象还可以通过类名() 的方式创建,这样的对象叫匿名对象声明周期 只有被创建的哪一行,该行执行完,对应的匿名对象就会被销毁。

class A
{
public:A(){cout << "A()" << endl;}A(int a, int b): _a(a), _b(b){cout << "A(int a, int b)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;int _b;
};int main()
{A();     //匿名对象A(1, 2); //匿名对象return 0;
}

在这里插入图片描述

使用场景:

如果我们需要创建对象,但对象创建后只使用一次,那就可以用匿名对象

注意:

匿名对象具有常性 ,需要使用引用接收匿名对象时需要使用const修饰。

4.友元

友元提供了一种突破封装的方法,有时提供便利,但友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元分为:友元函数友元类

4.1友元函数

友元函数定义在类外部的普通函数 ,不属于任何类,但需要在类的内部声明,声明时需要加friend 关键字。友元函数 可以 直接访问 类的私有 成员。

特性:

  • 友元函数 内类对象可访问类的私有和保护成员,但它不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数 可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同
class A
{
public:friend void test(A& a); //友元函数的声明A(int a,int b):_a(a),_b(b){}
private:int _a;int _b;
};void test(A& a)
{cout << a._a << endl;
}int main()
{A a(1, 2);test(a);return 0;
}

在这里插入图片描述

4.2友元类

友元类所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

注意:

  1. 友元关系是单向的,不具有交换性。

    在这里插入图片描述

  2. 友元关系不能传递

    如果A是B的友元,B是C的友元,则不能说明A是B的友元

    如果A是B的友元,C也是B的友元,也不能说明A和B一个是另一个的友元。

    在这里插入图片描述

  3. 友元关系不能继承

class A
{
public:friend class B;//友元类的声明A(): _Aa(1), _Ab(2){}private:int _Aa;int _Ab;
};class B
{
public:B(): _Ba(1), _Bb(2){A aa;cout << aa._Aa << " " << aa._Ab << " " << endl;}private:int _Ba;int _Bb;
};int main()
{B bb;return 0;
}

在这里插入图片描述

5.内部类

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

class A
{
public:A(): _Aa(1), _Ab(2){}class B{public:B(): _Ba(1), _Bb(2){A aa;cout << aa._Aa << " " << aa._Ab << " " << endl;}private:int _Ba;int _Bb;};private:int _Aa;int _Ab;static int _Ac;
};

特性:

  1. 内部类就是外部类的友元,内部类可以通过外部类的对象参数来访问外部类中的所有成员,但外部类不是内部类的友元。

  2. 内部类可以定义在外部类的public、protected、private都是可以的

  3. 想要创建一个内部类对象,需要通过外部类指定

    int main()
    {A::B bb;//创建内部类return 0;
    }
    

    在这里插入图片描述

  4. 注意内部类可以直接访问外部类中的static成员,不需要外部里的对象/类名。

    注意:友元类不可以直接访问static成员

  5. sizeof(外部类) = 外部类,和内部类没有任何关系。

    int main()
    {cout << sizeof(A) << endl;return 0;
    }
    

    在这里插入图片描述

  • 对于内部类,我们只做了解就好,在C++中很少用到内部类,而java中内部类用的倒是很多。

6.拷贝对象时的一些编译器优化

在传参和传返回值的过程中,一般编译器会做出一些优化,减少对象的拷贝,这个在一些场景下可以帮我们提高程序的运行速率。

创建如下类,通过下面这个类创建的对象进行操作,观察现象,搞清楚编译器的优化

class A
{
public:A(int aa = 0):_a(aa){cout << "A()" << endl;}~A(){cout << "~A" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& a)" << endl;}A& operator=(const A& aa){if (&aa != this){_a = aa._a;}cout << "A& operator=(const A& a)" << endl;return *this;}
private:int _a;
};

在上面讲explicit关键字时,我们已经知道了类型替换的概念,知道编译器会优化一些步骤使之更加便捷,下面我们针对这一现象再来研究一下

6.1传值传参

void test1(A aa)
{}void test3(const A& aa)
{}int main()
{A aa1;//构造test1(aa1);//拷贝构造cout << "-----------------" << endl;test3(aa1);//引用传参,对象已存在无需进行构造或拷贝cout << "-----------------" << endl;test1(A(1));//匿名对象构造+拷贝构造 -> 优化为直接构造cout << "-----------------" << endl;test1(1);//隐式类型,构造+拷贝构造 -> 优化为直接构造return 0;
}

在这里插入图片描述

对于正常的创建对象,之后将对象传递给参数,这样的操作,虽然也进行了构造和拷贝两个步骤,但它是在两行上分别执行的,绝大多数编译器都不会在此处进行优化。(一些比较激进的编译器会这样做)

对于引用传参,因为对象已经创建好了,直接引用即可,只执行了一个构造,而且函数执行完后还可以接着使用,但注意,若传过去的对象不会改变,建议使用const修饰,防止发生变化。

对于使用匿名对象传参隐式类型替换 为对象的操作,正常来看都需要经过构造、拷贝两个步骤,形参才会被赋予数据,而经过编译器优化后省去了拷贝的步骤,直接使用初始化的值构造形参。但对象在函数执行完后就无法在使用。

6.2传值返回

A test2()
{A a;return a;
}A test4()
{return A(1);
}int main()
{test2();//构造+拷贝构造cout << "-----------------" << endl;A aa2 = test2();//构造+拷贝构造+拷贝构造 -> 优化为:构造 + 拷贝构造cout << "-----------------" << endl;A aa1;//构造aa1 = test2();//构造+拷贝构造+赋值重载cout << "-----------------" << endl;A aa3 = test4();//使用匿名对象返回,构造+拷贝+拷贝 -> 构造cout << "-----------------" << endl;return 0;
}

在这里插入图片描述

对于传值返回中的第16行代码,返回值由一个未定义的对象接收,意味着以返回对象为参数,调用拷贝构造函数,定义该对象,所以该行代码的执行步骤应该为:构造、拷贝、拷贝编译器对其进行优化,将原本test2中返回时需要拷贝出一个临时对象的操作,优化为直接拷贝出所接收的对象,将两个拷贝优化为一个拷贝。

在这里插入图片描述

对于第19行,因为对象以及定义,使用定义好的对象接收返回对象,这里就是赋值重载,对于赋值重载无法进行优化。

对于21行,接收匿名函数返回的对象,原本应该是匿名对象调用构造函数创建对象,之后拷贝一个临时对象,由临时对象在经过拷贝创建出所要的对象,经过编译器优化,两次拷贝都不在调用,因为匿名对象只执行一行,对象返回后就会被销毁,编译器直接使用匿名对象构造出的对象作为接收返回值的对象,所得结果相同,但过程更为简洁。

在这里插入图片描述

总结:

  • 对象传参

    尽量使用引用接收参数

  • 对象返回

    1. 接收返回值对象,尽量使用拷贝方法接收,不要使用赋值接收
    2. 函数中返回对象时,尽量返回匿名对象。

7.理解类和对象

对于现实生活中的实体,计算机是不认识的,计算机只认识二进制格式的数据。如果想要让计算机认识现实生活中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创建对象后计算机才可以认识。

比如说我们使用的手机实体,想要认识让计算机认识手机,需要经过以下步骤:

  1. 先对现实生活中手机实体进行抽象—即在人为思想层面对手机进行认识,手机有什么属性,有那些功能,即对手机进行抽象认知的一个过程。
  2. 经过1后,在人的头脑中已经对手机有了一个清醒的认识,只不过此时计算机还不清楚,想要让计算机识别人想象中的手机,就需要人通过某种面向对象的语言(如:Java、C++、Python等)将手机用类来进行描述,并输入到计算机中。
  3. 经过2后,在计算机中就有了一个手机类,但手机类只是站在计算机的角度对手机对象进行描述的,通过手机类,可以实例化出一个个具体的手机对象,此时计算机才能知道手机是什么东西。
  4. 此时用户就可以借助计算机中手机对象,来模拟现实中的手机实体了。

在类和对象阶段,大家一定要体会到:

类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,用该自定义类型就可以实例化具体的对象。

在这里插入图片描述

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

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

相关文章

java中字符串首字母变大写的两种方法

public class 快速排序 {public static void main(String[] args) {int[] arr new int[]{5, 2, 9, 6, 22, 21};//System.out.println(Arrays.toString(kuaiPai(arr)));// System.out.println(Arrays.asList("dada", "dda", "ddd"));//System.o…

学完Scrapy-Splash秒变爬虫大佬

在做爬虫的时候&#xff0c;大多数的网页中会存在数据动态加载的部分&#xff0c;而且多数都是后期渲染上的。正常情况下爬虫程序仅能爬取被渲染过的数据。因此我们看到的数据也许并非是爬虫直接获取来的。 而scrapy-splash担任了一个中间人的角色&#xff0c;程序通过splash服…

Vue3代码初体验找不同

文章目录&#x1f31f; 写在前面&#x1f31f; 代码分析&#x1f31f; 写在最后&#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 Vue3 的相关技术文章&#xff0c;Vue 框架目前的地位大家应该都晓…

Echarts 设置折线图拐点的颜色,边框等样式,hover时改变颜色

第014个点击查看专栏目录上一篇文章我们讲到了如何设置拐点大小,图形类型&#xff0c;旋转角度&#xff0c;缩放同比&#xff0c;位置偏移等&#xff0c;这篇文章介绍如何设置拐点的颜色、边框大小颜色等样式。hover轴线时候&#xff0c;拐点的填充颜色改变文章目录示例效果示例…

python笔记-- “__del__”析构方法

-#### 1、基本概念&#xff08;构造函数与析构函数&#xff09; 特殊函数&#xff1a;由系统自动执行&#xff0c;在程序中不可显式地调用他们 构造函数&#xff1a; 建立对象时对对象的数据成员进行初始化&#xff08;对象初始化&#xff09; 析构函数&#xff1a; 对象生命期…

解决需求变更难题的8大方案

需求变更8大原因为什么会出现需求变更&#xff0c;这是由于需求约束、规则有了新的变化、由于政策发生变化&#xff0c;客户、沟通方式、流程化、标准化的问题等导致。这里在在过去的项目经验中&#xff0c;提出了常见的8大需求变更的原因。政策发生变化&#xff1a;指由于国家…

Linux/CenterOS 7.9配置汉化gitlab服务器

1.安装gitlab的依赖项 yum install -y curl openssh-server openssh-clients postfix cronie policycoreutils-python2.启动postfix&#xff0c;并设置为开机启动 systemctl start postfixsystemctl enable postfix3.防火墙和selinux的设置 setenforce 0systemctl stop fire…

【macOS】mac电脑M2芯片安装Homebrew 最简单的方法

一 Homebrew的安装 打开终端&#xff0c;复制如下命令&#xff0c;按回车执行 M芯片和Intel芯片均可 中途可能需要你手动输入密码&#xff0c;输入完成回车即可&#xff08;密码不可见 选择中科大或者清华镜像源 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/Hom…

最接近的三数之和-力扣16-java排序+双指针

一、题目描述给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在恰好一个解。示例 1&#xff1a;输入&#xff1a;nums [-1,2,1,-4], target 1输出&#xff…

revit中如何创建有坡度的排水沟及基坑?

一、revit中如何创建有坡度的排水沟? 先分享一张有坡度排水沟的族的照片给大家加深一下印象&#xff0c;有了一个粗略的直观认识&#xff0c;小编就来说说做这个族的前期思路吧。 一、前期思路&#xff1a; 1、 用拼接的方式把这个族形状拼出来&#xff0c;先用放样&#xff0…

Vue3 中 axios 的安装及使用

目录前言&#xff1a;一、什么是 axios &#xff1f;二、Axios 的配置项三、Axios 的请求方式四、自定义创建实例五、Axios 请求错误处理六、Axios 解决跨域问题七、Axios 请求案例随机笑话大全总结&#xff1a;前言&#xff1a; 在编写vue里的项目时&#xff0c;必须要用和后台…

【数据库】MySQL的sql语句详解

目录 MySQL之sql语句 一&#xff0c; INSERT语句 insert语句的使用&#xff1a; 1&#xff0c;给表中一次性插入一条记录 2&#xff0c;给表中一次性插入多条记录 二&#xff0c; REPLACE语句 REPLACE语句的使用 1&#xff0c;语法一 2&#xff0c;语法二 3&#xff…

Linux环境变量讲解

目录 环境变量 alias命令 type命令 变量分类 Linux最主要的全局环境变量 环境变量 变量是计算机系统用于保存可变数值的数据类型 在Linux中&#xff0c;一般变量都是大写&#xff0c;命令是小写 在Linux中&#xff0c;变量直接使用&#xff0c;不需要定义&#xff08;更快…

加入bing体验chatGPT大军中来吧,它来了!

1 第一步&#xff1a;加入候选名单 1、首先需要加入候选名单 https://www.microsoft.com/zh-cn/edge?formMA13FJ 2、下载最新的Edge浏览器、androd、iOS都有试用版本&#xff08;可以看到iOS加护当前已满&#xff09; 这里我下载的是dev版本&#xff0c;Canary版本由于是…

点云转3D网格【Python】

推荐&#xff1a;使用 NSDT场景设计器 快速搭建 3D场景。 在本文中&#xff0c;我将介绍我的 3D 表面重建过程&#xff0c;以便使用 Python 从点云快速创建网格。 你将能够导出、可视化结果并将结果集成到您最喜欢的 3D 软件中&#xff0c;而无需任何编码经验。 此外&#xff0…

sni+tomcat漏洞复现

sni SNI产生背景 SSL以及TLS&#xff08;SSL的升级版&#xff09;为客户端与服务器端进行安全连接提供了条件。但是&#xff0c;由于当时技术限制&#xff0c;SSL初期的设计顺应经典的公钥基础设施 PKI(Public Key Infrastructure)设计&#xff0c;PKI 认为一个服务器只为一个…

我用python/C++调用ChatGPT自制了一个聊天机器人

目录1 ChatGPT完整版2 Python/C调用ChatGPT2.1 获取API秘钥2.2 测试API功能2.3 设计简单UI3 聊天问答1 ChatGPT完整版 2015年&#xff0c;OpenAI由马斯克、美国创业孵化器Y Combinator总裁阿尔特曼、全球在线支付平台PayPal联合创始人彼得蒂尔等硅谷科技大亨创立&#xff0c;公…

chatGPT都可以干什么呢?来一睹风采 (送账号)

文章目录1. 写代码2. 写文案3. 写剧本4. 写歌诗5. 写报告6. 查公式7. 写对联8. 写文章9. 做表格10. 做计划11. 等等1. 写代码 2. 写文案 3. 写剧本 4. 写歌诗 5. 写报告 这妥妥的翻译文&#xff0c;数据完全不对。 6. 查公式 傅里叶变换的时域性质有如下几点&#xff1a; 对…

企业三要素核验API接口,你了解多少?

企业三要素核验API接口是指哪些要素&#xff1f;企业三要素是一种有关企业实名认证的应用程序接口也称API&#xff0c;企业的名称、统一社会信用代码和法人代表姓名统称企业三要素。企业三要素核验API接口的资源来自国家工商总局数据库&#xff0c;通过数据库资料三个要素进行核…

ChatGPT 可以联网了!浏览器插件下载

注册看这里&#xff1a;https://www.cnblogs.com/ranxi169/p/16954797.html Twitter 用户 An Qu 开发了一款新的 Chrome 插件帮助 ChatGPT 上网&#xff0c;安装插件以后 ChatGPT 就可以联&#xff01;网&#xff01;了&#xff01; 简单来说开启插件后&#xff0c;他可以从网…