6-继承

6-继承

  • 1、基本语法和方式
  • 2、继承的基本特点
    • 2.1 三种继承方式相同的基本点
    • 2.2 三种继承方式的差别
    • 2.3 公有继承的独有特点
  • 3、子类的构造、析构
    • 3.1 子类的构造
    • 3.2 子类的析构
    • 3.3 子类的拷贝构造函数
    • 3.4 子类的拷贝赋值
  • 4、多重继承
    • 4.1 内存布局
    • 4.2 类型转换
    • 4.3 名字冲突问题
  • 5、砖石继承
  • 6、虚继承

1、基本语法和方式

class 子类 : 继承方式1 基类1, 继承方式2 基类2, ... {...
};
  • 继承方式
    公有继承:public
    保护继承:protected
    私有继承:private

2、继承的基本特点

2.1 三种继承方式相同的基本点

  • 继承所要达到的目的:
    • 子类对象包含基类子对象
    • 子类内部可以直接访问基类的所有非私有成员
  • 继承的本质:
    • 基类的非私有成员在子类中仅仅为可见,而非拥有
      注意:
      对于继承切忌不要理解为基类的成员变为子类的成员,继承不会改变类成员的作用域,基类的成员永远都是基类的成员,并不会因为继承而变成子类的成员
  • 尽管基类的公有和保护成员在子类中直接可见,但仍然可以在子类中重新定义这些名字,子类中的名字会隐藏所有基类中的同名定义
  • 如果需要在子类内部访问 一个在基类中定义却被子类标识符所隐藏的名字,可以借助作用域限定操作符“::”实现
  • 因为作用域的不同,分别在子类和基类中定义的同名成员函数(包括静态成员函数),并不构成重载关系,相反是一种隐藏关系
  • 任何时候,在子类的内部,总可以通过作用域限定操作符“::”,显式地调用那些在基类中定义却被子类所隐藏的成员
// 继承最基本的特点
// (1) 子类对象的内部 包含 基类子对象
// (2) 子类内部可以直接访问 基类的 非私有(共有/保护)成员(变量/函数)
// (3) 一旦被子类同名定义隐藏 可以借助::指明访问基类
class Base{
public:int m_a;void foo(){ cout << "Base::foo" << endl; }
protected:int m_b;void bar(){ cout << "Base::Bar" << endl; }
private:int m_c;void hum(){ cout << "Base::hum" << endl; }
};
class Derived :public Base{
public:void fun(){m_a = 100;Base::foo();// 子类的foo函数将基类的foo函数隐藏,但可以通过作用域限定符访问基类的foom_b = 100;bar();  //子类内部可以直接访问 基类的 非私有(共有/保护)成员(变量/函数)//m_c = 100;//hum();}
private:int m_d;void foo(){ cout << "Derived::foo" << endl; }void bar(){ cout << "Derived::Bar" << endl; }
};
int main(){Base b;// 基类对象cout << "基类对象b的大小" << sizeof(b) << endl; // 12Derived d;// 子类对象cout << "子类对象d的大小" << sizeof(d) << endl; // 16  子类对象的内部 包含 基类子对象d.fun();return 0;
}

2.2 三种继承方式的差别

  • 基类中的公有、保护和私有成员,在子类中将对这些基类成员的访问控制限定进行重新标记
// public继承的独特点
class publicBase :public Base{// 子类将对基类的成员重新标记访问限定符// 子类将对基类的成员重新标记访控限定 m_a/foo是public m_b/bar是protected m_c/hum是private
public:void fun(){ // //子类内部访问基类成员时,编译器需要查看这些成员在 基类中的原始标记m_a = 100;Base::foo();// 子类的foo函数将基类的foo函数隐藏,但可以通过作用域限定符访问基类的foom_b = 100;bar();  //子类内部可以直接访问 基类的 非私有(共有/保护)成员(变量/函数)}
private:int m_d;
};
// protected继承的独特点
class protectedBase :protected Base{// 子类将对基类的成员重新标记访问限定符// 子类将对基类的成员重新标记访控限定 m_a/foo是protected m_b/bar是protected m_c/hum是private
public:void fun(){ //子类内部访问基类成员时,编译器需要查看这些成员在 基类中的原始标记m_a = 100;Base::foo();// 子类的foo函数将基类的foo函数隐藏,但可以通过作用域限定符访问基类的foom_b = 100;bar();  //子类内部可以直接访问 基类的 非私有(共有/保护)成员(变量/函数)}
private:int m_d;
};
// private继承的独特点
class privateBase :private Base{// 子类将对基类的成员重新标记访问限定符// 子类将对基类的成员重新标记访控限定 m_a/foo是private m_b/bar是private m_c/hum是private
public:void fun(){ //子类内部访问基类成员时,编译器需要查看这些成员在 基类中的原始标记m_a = 100;Base::foo();// 子类的foo函数将基类的foo函数隐藏,但可以通过作用域限定符访问基类的foom_b = 100;bar();  //子类内部可以直接访问 基类的 非私有(共有/保护)成员(变量/函数)}
private:int m_d;
};
int main(){publicBase d;// 利用子类对象在类外访问 基类成员时,编译器需要查看这些成员在 子类中的重新标记d.m_a = 10;d.foo();//d.m_b = 10; // err//d.bar();// err//d.m_c = 30;// err//d.hum();// errprotectedBase b;// 利用子类对象在类外访问 基类成员时,编译器需要查看这些成员在 子类中的重新标记//b.m_a = 10;// err//b.foo();// err//b.m_b = 10; // err//b.bar();// err//b.m_c = 30;// err//b.hum();// errprivateBase cd;// 利用子类对象在类外访问 基类成员时,编译器需要查看这些成员在 子类中的重新标记//cd.m_a = 10;// err//cd.foo();// err//cd.m_b = 10; // err//cd.bar();// err//cd.m_c = 30;// err//cd.hum();// errreturn 0;
}
基类中的在公有子类中标记为在保护子类中标记为在私有子类中标记为
公有成员公有成员保护成员私有成员
保护成员保护成员保护成员私有成员
私有成员私有成员私有成员私有成员
  • “通过”子类访问其所继承的基类的成员时,需要考虑因继承方式对访问控制限定的影响

2.3 公有继承的独有特点

(1) 只有在公有继承下,子类对象在类外可以访问基类的 公有成员(其他继承不可以)
(2) 如果被子类同名标识符隐藏可以借助::指明访问基类的成员
(3) 只有在公有继承下 子类类型指针 和 基类类型指针 之间可以进行转换
子类类型引用 和 基类类型引用 之间可以进行转换

class publicBase :public Base{
public:void foo(){cout << "publicBase::foo" << endl;}
private:int m_d;
};
class Human{
public:int m_d;string m_name;
};
class Student :public Human{
public :int m_no;
};
int main(){publicBase b;b.m_a = 1000;b.foo(); // 调用的是自己的b.Base::foo(); // 调用的是基类的Human h;cout << "基类对象h的大小" << sizeof(h) << endl;Student s;cout << "子类对象s的大小" << sizeof(s) << endl;// 子类类型指针 和 基类类型指针Human* ph = &s; // Student* --> Human*// 子类类型引用 和 基类类型引用Human& rh = s;// 以上两种转换,编译器认为访问范围缩小,是安全的//Student* ps = &h;//Student& rs = h;// 以上两种转换,编译器认为访问范围扩大,是危险的Student* ps = static_cast<Student*> (&h);Student& rs = static_cast<Student&>(h);// 通过静态转换虽然可以成功,但是风险依旧存在,极其不建议这么使用Student* ps = static_cast<Student*>(ph);// ph 指向的就是C6_Student的对象Student& rs = static_cast<Student&>(rh);// rh 就是C6_Student对象的引用// 以上两种转换毫无风险,极其建议大家这么做// 基类指针或引用的实际目标,究竟是不是子类对象,完全由我们自己判断return 0;
}

向上造型:

  • 子类类型指针 隐式 转换为基类类型指针
  • 子类类型引用 隐式 转换为基类类型引用

3、子类的构造、析构

3.1 子类的构造

  • 子类没有定义构造函数
    • 编译器为子类提供的默认无参构造函数,定义基类子对象,并调用其基类的无参构造函数,构造该子类对象中的基类子对象。
  • 子类定义构造函数但没有在初始化表中指明基类部分构造方式
    • 定义基类子对象,并调用其基类的无参构造函数,构造该子类对象中的基类子对象。
  • 子类定义构造函数并在初始化表中指明基类部分构造方式
    • 定义基类子对象并 调用指明的其基类的构造函数。
  • 子类对象的构造过程
    • 构造基类子对象->构造成员变量->执行构造代码

3.2 子类的析构

  • 子类没有定义析构函数
    • 编译器将提供一个默认析构函数,析构完所有的成员变量以后,会自动调用其基类的析构函数.
  • 子类定义析构函数
    • 子类的析构函数在执行完自身析构代码,并析构完所有的成员变量以后,会自动调用其基类的析构函数.
  • 子类对象的析构过程
    • 执行析构代码->析构成员变量->析构基类子对象

3.3 子类的拷贝构造函数

  • 子类没有定义拷贝构造函数
    • 编译器为子类提供的默认拷贝构造函数,定义基类子对象,并调用其基类的拷贝构造函数构造该子类对象中的基类子对象
  • 子类定义了拷贝构造函数,但没有在初始化表指明其基类部分的构造方式
    • 定义基类子对象,并调用其基类的无参构造函数,构造该子类对象中的基类子对象
  • 子类定义了拷贝构造函数,同时初始化表中指明了其基类部分以拷贝方式构造
    • 定义基类子类对象,并调用其基类的拷贝构造函数,构造该子类对象中的基类子对象

3.4 子类的拷贝赋值

  • 子类没有定义拷贝赋值函数
    • 编译器为子类提供的缺省拷贝赋值函数,会自动调用其基类的拷贝赋值函数,复制该子类对象中的基类子对象
  • 子类定义了拷贝赋值函数,但没有显式调用其基类的拷贝赋值函数
    • 子类对象中的基类子对象将得不到复制
  • 子类定义了拷贝赋值函数,同时显式调用了其基类的拷贝赋值函数
    • 子类对象中的基类子对象将得到复制
class C6_people{
public:C6_people(int age = 0, const char*name = "无名"):m_age(age), m_name(name){//【int m age=age;】定义mage,初值为age//【string m name(name);】定义m name,利用m name,string(name)cout << "people类的缺省构造函数被调用" << endl;}C6_people(const C6_people&that):m_age(that.m_age),m_name(that.m_name){// 【int m_age = that, mage; 】定义mage, 初值为that.m age//【string m name=that.m name;】定义m name,利用m name.string(that.m name)cout << "people类的拷贝构造函数被调用" << endl;}C6_people&operator=(const C6_people& that){//编译器不会在自定义拷贝赋值函数中塞任何操作cout << "people类的拷贝赋值函数被调用" << endl;this->m_age=that.m_age;this->m_name=that.m_name; // this->m name.operator=(that.m name)return *this;}~C6_people(){cout << "C6_people类的析构函数被调用" << endl;//对于基本类型的成员变量m_age,什么都不做//对于类类型的成员变量m_name,利用m_name,~string()//释放m_age/m_name本身所占内存空间}void getinfo(){cout << "姓名:" << m_name << ",年龄:" << m_age ;}
private:int m_age;// 基本类型成员变量string m_name;// 类类型成员变量
};
class C6_stu : public C6_people{
public://子类没有定义构造函数编译器为子类提供的默认无参构造函数//C6_stu(){//	【Human(); 】定义基类子对象,利用基类子对象.Human()//  【float m score; 】//	【string m remark; 】//}C6_stu(int age = 45, string name = "张三", float score = 0.0, string remark = "优秀") :m_score(score), m_remark(remark), C6_people(age,name.c_str()){cout << "基类的缺省构造被调用了" << endl;}void getinfo(){C6_people::getinfo();cout << "分数:" << m_score << "评语:" << m_remark << endl;}//子类没有定义析构函数编译器将提供一个默认析构函数//~C6_stu(){//对于基本类型的成员变量m_score,什么都不做//对于类类型的成员变量m m_remark,利用m_remark,~string()// 对于基类子对象,利用基类子对象.~C6_people()//释放m_score/m_remark本身所占内存空间//}~C6_stu(){cout << "C6_stu类的析构函数被调用" << endl;}//子类没有定义拷贝构造函数编译器为子类提供的默认拷贝构造函数//C6_stu(const C6_stu& that){//	// [C6_people(that)] 定义基类子对象,利用基类子对象.C6_people(that) ->C6_people类拷贝构造函数//	// ...//}// 子类没有定义拷贝赋值函数编译器为子类提供的缺省拷贝赋值函数//C6_stu& operator=(const C6_stu& that){//	C6_people *p = this;//	*p = that;// C6_people类的拷贝赋值函数//}private:float m_score;string m_remark;
};
int main(){cout << "----s1" << endl;C6_stu s1(22,"李四",89.7,"良好");// 构造s1.getinfo();cout << "----s2" << endl;C6_stu s2 = s1; // 拷贝构造s2.getinfo();cout << "----s3" << endl;C6_stu s3;cout << "s3赋值前" << endl;s3.getinfo();s3 = s2; // 赋值拷贝cout << "s3赋值后" << endl;s3.getinfo();return 0;
}

4、多重继承

4.1 内存布局

  • 子类对象中的多个基类子对象,按照继承表的顺序依次被构造,析构的顺序则与构造严格相反,各个基类子对象按照从低地址到高地址排列
    在这里插入图片描述
class C06_A{
public:int m_a;C06_A(){ cout << "C06_A构造" << endl; }~C06_A(){ cout << "C06_A析构" << endl; }
};
class C06_B{
public:int m_b;C06_B(){ cout << "C06_B构造" << endl; }~C06_B(){ cout << "C06_B析构" << endl; }
};
class C06_C{
public:int m_c;C06_C(){ cout << "C06_C构造" << endl; }~C06_C(){ cout << "C06_C析构" << endl; }
};
class C06_D :public C06_A, public C06_B, public C06_C{ // 汇聚子类
public:int m_d;C06_D(){ cout << "C06_D构造" << endl; }~C06_D(){ cout << "C06_D析构" << endl; }
};
int main(){C06_D d;cout << "汇聚子类对象d的大小:" << sizeof(d) << endl;C06_D * pd = &d;cout << "整个汇聚子类对象的首地址D* pd:" << pd << endl;cout<< "A基类子对象的首地址:" << &d.m_a<<endl;cout << "B基类子对象的首地址:" << &d.m_b << endl;cout << "C基类子对象的首地址:"<<&d.m_c<< endl;cout << "D基类子对象的首地址:" << &d.m_d << endl;return 0;
}

4.2 类型转换

  • 将多重继承的子类对象的指针,隐式转换为它的基类类型,编译器会根据各个基类子对象在子类对象中的内存位置,进行适当的偏移计算
  • 反之,将任何一个基类类型的指针静态转换为子类类型,编译器同样会进行适当的偏移计算
  • 无论在哪个方向上,重解释类型转换(reinterpret_cast)都不进行任何偏移计算–不要使用
    在这里插入图片描述
int main(){C06_D d;cout << "汇聚子类对象d的大小:" << sizeof(d) << endl;C06_D * pd = &d;cout << "整个汇聚子类对象的首地址D* pd:" << pd << endl;// 004FF730cout << "A基类子对象的首地址:" << &d.m_a << endl; // 004FF730cout << "B基类子对象的首地址:" << &d.m_b << endl; // 004FF734cout << "C基类子对象的首地址:" << &d.m_c << endl; // 004FF738cout << "D基类子对象的首地址:" << &d.m_d << endl; // 004FF73CC06_A* pa = pd;cout << "隐式转换" << endl;cout << "D* pd ---> A* pa:" << pa << endl; // 004FF730C06_B* pb = pd;cout << "D* pb ---> B* pb:" << pb << endl; // 004FF734C06_C* pc = pd;cout << "D* pd ---> C* pc:" << pc << endl; // 004FF738cout << "静态转换" << endl;C06_D* p1 = static_cast<C06_D*>(pa);cout << "A* pd ---> D* p1:" << p1 << endl; // 004FF730C06_D* p2 = static_cast<C06_D*>(pb);cout << "B* pb ---> D* p2:" << p2 << endl; // 004FF730C06_D* p3 = static_cast<C06_D*>(pc);cout << "C* pc ---> D* p3:" << p3 << endl; // 004FF730return 0;
}
  • 引用的情况与指针类似,因为引用的本质就是指针
    在这里插入图片描述

4.3 名字冲突问题

  • 如果在子类的多个基类中,存在同名的标识符,那么任何试图通过子类对象,或在子类内部访问该名字的操作,都将引发歧义。
    名字冲突问题解决方法
  • 子类隐藏该标识符–不建议使用
  • 通过作用域限定操作符“::”显式指明所属基类
class C06_E{
public:int m_a;int m_c;
};
class C06_F{
public:int m_b;int m_c;
};
class C06_G :public C06_E, public C06_F{
public:int m_d;void foo(){// m_c = 100;歧义C06_E::m_c = 100;}
};
int main(){C06_G g;cout << "汇聚子类对象g的大小:" << sizeof(g) << endl;// g.m_c=100; 歧义g.C06_E::m_c = 100;return 0;
}

5、砖石继承

  • 砖石继承的问题
    一个子类继承自多个基类,而这些基类又源自共同的祖先,这样的继承结构称为钻石继承(菱形继承)
    在这里插入图片描述
class C06_AA{ // 公共基类
public:int m_a;
};
class C06_X :public C06_AA{ // 中间子类
public:int m_x;
};
class C06_Y :public C06_AA{ // 中间子类
public:int m_y;
};
class C06_Z :public C06_X, public C06_Y{ // 汇聚子类
public:int m_z;
};
int main(){C06_Z z; // X中间子类子对象|Y中间子类子对象|m_z|-->// A公共基类子对象 m_x|A公共基类子对象 m_y|m_z|-->// m_a m_x |m_a m_y|m_z|cout << "汇聚子类对象g的大小:" << sizeof(z) << endl;// 20return 0;
}
  • 钻石继承问题
    在汇聚子类内部,或通过汇聚子类对象,访问公共基类的成员,会因继承路径的不同而导致匹配歧义

6、虚继承

解决砖石继承存在的问题而诞生的

  • 在继承表中使用virtual关键字

  • 虚继承可以保证
    (1)公共虚基类子对象在汇聚子类对象中仅存一份实例
    在这里插入图片描述

    (2)公共虚基类子对象被多个中间子类子对象所共享
    虚继承实现原理

  • 汇聚子类对象中的每个中间子类子对象都持有一个指针,通过该指针可以获取中间子类子对象的首地址公共虚基类子对象的首地址的偏移量
    在这里插入图片描述

class C06_AA{ // 公共基类
public:int m_a;
};
class C06_X :virtual public C06_AA{ // 中间子类
public:int m_x;void setAge(/* X* this */int age){m_a = age; // this -> X 中间子类子对象-》指针1-》偏移量-》this+偏移量-》A公共基类子对象-》m_a}};
class C06_Y :virtual public C06_AA{ // 中间子类
public:int m_y;int getAge(/* Y* this*/){ return m_a;// this->Y 中间子类子对象 - 》指针2 - 》偏移量 - 》this + 偏移量 - 》A公共基类子对象 - 》m_a}
};
class C06_Z :public C06_X, public C06_Y{ // 汇聚子类
public:int m_z;
};
int main(){C06_Z z; // X中间子类子对象|Y中间子类子对象|m_z|A公共基类子对象|-->// 指针1 m_x |指针2 m_y|m_z|m_a|cout << "汇聚子类对象g的大小:" << sizeof(z) << endl;// 32z.setAge(100); // setAge(&z) -->实参类型Z*cout << "age:" << z.getAge() << endl; // getAge(&z) -->实参类型Z*return 0;
}

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

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

相关文章

10. C++异步IO处理库和使用libevent实现高性能服务器

C比较有名的异步IO处理库 libevent 这个主要使用的是epoll。libevthplibuvlibev 我们主要介绍libevent。 libevent重要函数 event_base_new 这个可以对应于epoll_create也就是创建一个实例。还可以初始化libevent所有管理相关的代码。比如说所能用到的队列&#xff0c;栈&a…

电脑重装系统的PE工具

10款PE制作工具&#xff01;一键制作U盘启动盘&#xff0c;轻松制作系统盘&#xff0c;重装系统&#xff0c;免费纯净、无捆绑。 二、资源/简介 1.微PE工具箱 非常老牌的PE工具&#xff0c;装机维护得力的助手&#xff0c;最后的救命稻草。化繁为简&#xff0c;小材大用&…

【GPT‑4o】完整教程:LORA微调LLaMA3并结合RAG和Agent技术实现Text2SQL任务

完整教程&#xff1a;LORA微调LLaMA3并结合RAG和Agent技术实现Text2SQL任务 环境准备 首先&#xff0c;安装必要的Python包&#xff1a; pip install transformers peft datasets torch faiss-cpu加载LLaMA3模型 从Hugging Face加载LLaMA3模型和对应的tokenizer&#xff1a…

算法基础之集合-Nim游戏

集合-Nim游戏 核心思想&#xff1a; 博弈论 sg函数&#xff1a;在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1,y2,yk,定义SG(x)的后记节点y1,y2,,yk的SG函数值构成的集合在执行mex运算的结果,即:SG(x)mex({SG(y1),SG(y2)SG(yk)}) **特别地,**整个有向图…

Linux内核编译流程3.10

一、内核源代码编译流程 编译环境&#xff1a; cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) Linux内核版本&#xff1a; uname -r 3.10.0-693.el7.x86_64 编译内核源代码版本&#xff1a;linux-4.19.90-all-arch-master cp /boot/config-xxx到内核源…

数据库(9)——DQL基础查询

数据查询 数据查询是SQL中最复杂的&#xff0c;语法结构为 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后字段列表 ORDER BY 排序字段列表 LIMIT 分页参数 查询多个字段 SELECT 字段1&#xff0c;字段2...FROM…

领域驱动设计(DDD)学习笔记之:战略设计

限界上下文&#xff08;Bounded Context&#xff09; 上下文边界的确定 在领域驱动设计&#xff08;DDD&#xff09;中&#xff0c;限界上下文&#xff08;Bounded Context&#xff09;是定义领域模型边界的核心概念。明确和定义上下文边界是DDD战略设计中的重要步骤。正确地…

Spring Cloud:微服务架构的基石

目录 微服务架构简介 Spring Cloud 简介 Spring Cloud 组件详解 Eureka 服务注册与发现 Ribbon 负载均衡 Feign 声明式 HTTP 客户端 Hystrix 服务容错保护 Zuul 网关 Config 配置管理 Sleuth 链路追踪 Spring Cloud Stream 消息驱动 Spring Cloud 与 Docker 的结合 …

LeetCode583:两个字符串的删除操作

题目描述 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 代码 解法1 /*dp[i][j]&#xff1a;以i-1为结尾的wrod1中有以j-1为尾的word2的个数为了让word1和word2相同&#xff0c;最少操作…

linux开发之设备树基本语法一

设备树的根节点 设备树子节点和子子节点,子节点在根节点范围内 包含子节点以及子子节点 节点名称 比如这里led就是这个gpio的小名,可以直接用 gpio22020101是这里的名字,也就是要用这个gpio,符号后面的一串数字使用了这个gpio的寄存器地址,因为可能会用很多gpio,所以加入寄存…

Linux完整版命令大全(二十二)

uux 功能说明&#xff1a;在远端的UUCP主机上执行指令。语  法&#xff1a;uux [-bcCIjlnrvz][-a<地址>][-g<等级>][-s<文件>][-x<层级>][--help][指令]补充说明&#xff1a;uux可在远端的UUCP主机上执行指令或是执行本机上的指令&#xff0c;但在执…

Pushmall共享分销电商SaaS版2024年 5月模块开发优化完成

Pushmall共享分销电商 2024年 5月模块开发优化完成 1、**实现SaaS框架业务&#xff1a;**多租户、多商家、多门店&#xff0c;及商家入驻、商品管理。 2、租户小程序管理&#xff1a;对租户的小程序业务管理。 3、店铺小程序管理&#xff1a;对租户多店铺小程序绑定。 4、会员分…

新火种AI|警钟长鸣!教唆自杀,威胁人类,破坏生态,AI的“反攻”值得深思...

作者&#xff1a;小岩 编辑&#xff1a;彩云 在昨天的文章中&#xff0c;我们提到了谷歌的AI Overview竟然教唆情绪低迷的网友“从金门大桥跳下去”。很多人觉得&#xff0c;这只是AI 模型的一次错误判断&#xff0c;不会有人真的会因此而照做。但现实就是比小说电影中的桥段…

精酿啤酒:品质与口感对啤酒市场价格的影响

啤酒作为一种大众化的产品&#xff0c;其品质与口感对市场价格有着显著的影响。对于Fendi club啤酒而言&#xff0c;其卓着的品质和与众不同的口感又加上市场价格相对实惠&#xff0c;受到消费者的青睐。 品质是决定啤酒市场价格的重要因素。Fendi club啤酒选用天然小麦原料&am…

【leetcode2765--最长交替子数组】

要求&#xff1a;给定一个数组&#xff0c;找出符合【x, x1,x,x-1】这样循环的最大交替数组长度。 思路&#xff1a;用两层while循环&#xff0c;第一个while用来找到符合这个循环的开头位置&#xff0c;第二个用来找到该循环的结束位置&#xff0c;并比较一下max进行记录。 …

太速科技-16通道24bit 256kHZ 的振动信号千兆网络采集器

16通道24bit 256kHZ 的振动信号千兆网络采集器 一、产品概述 数据采集器是一台运行Linux操作系统的智能终端&#xff0c;在以太网络的支持下&#xff0c;可迅速构建起大规模的分布式智能数据采集系统。采集器终端体积小&#xff0c;功耗低&#xff0c;易集成&#xff0c…

ubuntu linux (20.04) 源码编译cryptopp库 - apt版本过旧

下载最新版 https://www.cryptopp.com/#download 编译安装&#xff1a; ​#下载Cryptopp源码 #git clone https://gitee.com/PaddleGitee/cryptopp.git#进入文件夹 cd cryptopp #编译&#xff0c;多cpu处理 make -j8 #安装&#xff0c;默认路径&#xff1a;/usr/local sudo m…

Apache Impala 4.4.0正式发布了!

历时半年多&#xff0c;Impala 4.4终于发布了&#xff01;本次更新带来了不少新功能&#xff0c;受限于篇幅&#xff0c;这里简要列举一些&#xff0c;后续文章再挑重点的进行介绍。 支持更多Iceberg表上的语句 支持对 Iceberg V2 表的 UPDATE 语句&#xff0c;用来更新已有数…

解析新加坡裸机云多IP服务器网线路综合测评解析

在数字化高速发展的今天&#xff0c;新加坡裸机云多IP服务器以其卓越的性能和稳定性&#xff0c;成为了众多企业和个人用户的首选。源库主机评测将对新加坡裸机云多IP服务器的网线路进行综合测评&#xff0c;以帮助读者更深入地了解这一产品的优势。 一、性能表现 新加坡裸机云…

代码随想录算法训练营第四十三天 动态规划 part05● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

1049. 最后一块石头的重量 II 题目链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;主要是要找到两个近似相等的子集和&#xff0c;去求这两个和的最小值; 之后就是和从子集中找相对应和的思路是一样的了 注意点&#xff1a;1&#xff09;dp 初始…