c++_09_继承

1  继承

        C++的继承是弱继承 

        继承的语法:

                class  子类 : 继承方式1  基类1,  继承方式2  基类2,  ...  { ... };

        继承方式:

                共有继承  public

                保护继承  protected

                私有继承  private  

2  继承的基本属性(3种继承方式均有)

        继承所要达到的目的:

                子类对象包含基类子对象 

                子类内部可以直接访问基类的所有非私有成员

// derived.cpp 继承最基本的特点:
// (1) 子类对象 内部包含 基类(子)对象
// (2) 子类内部可以访问 基类的 非私有(公有/保护)成员(变量/函数)
#include <iostream>
using namespace std;
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 {
//class Derived : protected Base {
class Derived : private Base {
public:void fun() {m_a = 100; // okfoo();     // okm_b = 200; // okbar();     // ok, 以上四行代码证明子类内部可以直接访问基类的公有和保护成员
//      m_c = 300; // error
//      hum();     // error,以上两行代码证明子类内部不可以直接访问基类的私有成员}
private:int m_d;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Base b; // 基类对象-->|m_a m_b m_c|cout << "基类对象b的大小:" << sizeof(b) << endl; // 12Derived d; // 子类对象--> |基类子对象|m_d| --> |m_a m_b m_c|m_d|cout << "子类对象d的大小:" << sizeof(d) << endl; // 16return 0;
}

        继承的本质:

                基类的非私有成员在子类中仅为可见,而非子类拥有。 (可见表)(软继承)

        注意:关于继承,切记不要理解为基类的成员变为子类的成员。继承不会改变类成员的作用域,基类的成员永远都是基类的成员,并不会因为继承而变成子类的成员。

        尽管基类的公有和保护成员在子类中直接可见,但仍然可以在子类中重新定义这些名字,子类中的名字会隐藏所有基类中的同名定义(定义表隐藏可见表)。

        如果需要在子类内部访问一个基类中定义却被子类标识符所隐藏的名字,可以借助作用域限定操作符::实现。

        因为作用域的不同,分别在子类和基类中定义的同名成员函数(包括静态成员函数),并不构成重载关系,相反是一种隐藏关系。

// hide.cpp 基类和子类内部的同名定义 相互之间为隐藏关系 
#include <iostream>
using namespace std;
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 {
//class Derived : protected Base {
//class Derived : private Base {
public:void fun() {Base::foo(); // 子类的foo将基类的foo隐藏,但可以利用作用域限定符强制调用基类的foobar(); // 子类的bar将基类的bar隐藏}
private:int m_d;void foo() { cout << "Derived::foo" << endl; }void bar() { cout << "Derived::bar" << endl; }
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Derived d;d.fun();return 0;
}

3  三种继承方式的差别(不是重点)

        基类中的公有、保护、私有成员,在子类中将对这些基类成员的访问控制限定进行重新标记:

                          

       工作中主要使用public继承,其他极少使用。

        在类的外部,通过 子类对象   访问   基类的成员时,需要考虑因继承方式对访问控制限定的影响:

// public.cpp 公有继承
#include <iostream>
using namespace std;
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 {// 子类将对基类的成员重新标记访控限定 m_a/foo是public m_b/bar是protected // m_c/hum是private
public:void fun() { // 子类内部访问基类的成员,编译器需要查看这些基类成员在基类中的原始标记m_a = 100; // okfoo();     // okm_b = 200; // okbar();     // ok, 以上四行代码证明子类内部可以直接访问基类的公有和保护成员
//      m_c = 300; // error
//      hum();     // error,以上两行代码证明子类内部不可以直接访问基类的私有成员}
private:int m_d;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Derived d; // 利用子类对象在类外访问基类的成员,编译器需要查看这些成员在子类中的重新标记d.m_a = 1000; // okd.foo();      // ok
//    d.m_b = 2000; // error
//    d.bar();      // error
//    d.m_c = 3000; // error
//    d.hum();      // errorreturn 0;
}
// protected.cpp 保护继承
#include <iostream>
using namespace std;
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 : protected Base {// 子类将对基类的成员重新标记访控限定 m_a/foo是protected   m_b/bar是protected//m_c/hum是private
public:void fun() { // 子类内部访问基类的成员,编译器需要查看这些基类成员在基类中的原始标记m_a = 100; // okfoo();     // okm_b = 200; // okbar();     // ok, 以上四行代码证明子类内部可以直接访问基类的公有和保护成员
//      m_c = 300; // error
//      hum();     // error,以上两行代码证明子类内部不可以直接访问基类的私有成员}
private:int m_d;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Derived d; // 利用子类对象在类外访问基类的成员,编译器需要查看这些成员在子类中的重新标记
//    d.m_a = 1000; // error
//    d.foo();      // error
//    d.m_b = 2000; // error
//    d.bar();      // error
//    d.m_c = 3000; // error
//    d.hum();      // errorreturn 0;
}
// private.cpp 私有继承
#include <iostream>
using namespace std;
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 : private Base {// 子类将对基类的成员重新标记访控限定 m_a/foo是private   m_b/bar是private   //m_c/hum是private
public:void fun() { // 子类内部访问基类的成员,编译器需要查看这些基类成员在基类中的原始标记m_a = 100; // okfoo();     // okm_b = 200; // okbar();     // ok, 以上四行代码证明子类内部可以直接访问基类的公有和保护成员
//      m_c = 300; // error
//      hum();     // error,以上两行代码证明子类内部不可以直接访问基类的私有成员}
private:int m_d;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Derived d; // 利用子类对象在类外访问基类的成员,编译器需要查看这些成员在子类中的重新标记
//    d.m_a = 1000; // error
//    d.foo();      // error
//    d.m_b = 2000; // error
//    d.bar();      // error
//    d.m_c = 3000; // error
//    d.hum();      // errorreturn 0;
}

 

 

 

4  公有继承独有的特点

4.1  子类对象在类外可以访问基类公有成员

                如果被子类同名标识符隐藏,可借助作用域限定符::指定访问基类的公有成员。

// phs.cpp 公有继承独有特点:
// (1)只有在公有继承下,子类对象在类外可以访问基类的公有成员(其他继承不可以)
#include <iostream>
using namespace std;
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 foo() { cout << "Derived::foo" << endl; }
private:int m_d;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Derived d; d.m_a = 1000; // okd.foo();      // ok,只有在公有继承下,子类对象在类外可以访问基类的公有成员d.Base::foo();// okreturn 0;
}

 

4.2  子类类型的指针(引用) 和 基类类型的指针(引用)可以进行转换

        子类类型的指针 能 隐式转换为基类类型的指针 

        子类类型的引用 能 隐式转换为基类类型的引用

         (编译器认为访问范围缩小是安全的):

                                        

                                        class  Human { ... };

                                        class  Student : public Human { ... };

                                        Student s;

                                        Human*  ph = &s;  // 指针  访问范围缩小 

                                        Human&  rh = s;   //  引用  访问范围缩小

        基类类型的指针 能 隐式转换为子类类型的指针

        基类类型的引用 能 隐式转换为子类类型的引用

        (编译器认为访问范围扩大是危险的):

                                        class  Human { ... };

                                        class  Student : public Human { ... };

                                        Human h;

                                        Student*  ps = static_cast<Student*>(&h); // 指针  访问范围扩大 

                                        Student&  rs = static_cast<Student&>(h);  // 引用  访问范围扩大 

                                        

        编译器对类型安全的检测仅仅基于指针/引用本身

        基类指针/引用的实际目标,究竟是不是子类对象,完全由程序员自己判断:

                                        class  Human { ... };

                                        class  Student : public Human { ... };

                                        Student  s;

                                        Human*  ph = &s;

                                        Human&  rh = s;

                                        Student  ps = static_cast<Student*> (ph); // 访问范围扩大,但安全合理

                                        Student  rs = static_cast<Student&> (rh); // 访问范围扩大,但安全合理

                                        

#include <iostream>
using namespace std;
#pragma pack(1)
class Human {
public:int m_age;string m_name;
};
class Student : public Human {
public:int m_no;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {Human h; // |m_age m_name|cout << "基类对象h的大小:" << sizeof(h) << endl; // 36Student s; // |基类子对象|m_no| --> |m_age m_name|m_no|cout << "子类对象s的大小:" << sizeof(s) << endl; // 40Human* ph = &s; // Student*-->Human* (子类型指针-->基类型指针)Human& rh = s;  // 以上两种转换编译器认为访问范围缩小,是安全的//    Student* ps = static_cast<Student*>(&h); // Human*-->Student* // (基类型指针-->子类型指针)
//    Student& rs = static_cast<Student&>(h);  // 以上两种转换编译器认为访问范围扩大,是危险的,通过强转虽然可以成功,但风险依然存在// (极其不建议大家这么做)Student* ps = static_cast<Student*>(ph);//Human*-->Student*(基类型指针-->子类型指针)Student& rs = static_cast<Student&>(rh);//Human&-->Student&(基类型引用-->子类型应用)// 以人类高智商判断以上两个转换毫无风险(极其建议大家这么做) // 编译器只是简单粗暴的根据类型来判断是否存在风险return 0;
}

5  子类的构造和析构

5.1  子类的构造函数

        1)子类没有定义构造函数时:

                        编译器会为子类提供默认的无参构造函数 

                        定义完基类子对象后,调用基类无参构造函数 

        2)子类定义构造函数,但未在初始化表中指明基类部分的构造方式时:

                        定义完基类子对象后,调用基类无参构造函数 

        3)子类定义构造函数,并且在初始化表中指明基类部分的构造方式时:

                        定义完基类子对象后,调用指明的基类的构造函数

        子类对象的构造过程:

        1)构造基类子对象   2)构造子类的成员变量   3)执行自己在子类构造函数中书写的代码

        

        阻断继承:

                子类的构造函数  无论如何  都会调用基类的构造函数。

                若把基类的构造函数定为私有,则该类的子类就永远不能被实例化为对象。

                在C++中可以用这种方法阻断一个类被扩展。

5.2  子类的析构函数

        1)子类没有定义析构函数时:

                编译器将提供一个默认的析构函数,析构完子类所有的成员变量后,

                会自动调用其基类的析构函数

        2)子类定义了析构函数时:

                子类的析构函数在执行完自身析构代码,并析构完所有的成员变量后,

                会自动调用其基类的析构函数

        

        子类对象的析构过程:

        1)执行自己在子类析构函数中书写的代码    2)析构子类的成员变量    3)析构基类子对象

         

5.3  子类的拷贝构造函数

        1)子类并没有定义拷贝构造函数时:

                编译器会为子类提供默认的拷贝构造函数,

                定义完基类子对象后,调用基类的拷贝数构造函 。

        2)子类定义了拷贝构造函数,但没有在初始化表中指明其基类部分的构造方式时:

                定义完基类子对象后,调用基类的无参构造函数。

        3)子类定义了拷贝构造函数,且初始化表中指明了其基类部分以拷贝方式构造时:

                定义完基类子对象后,调用基类的拷贝构造函数。

5.4  子类的拷贝赋值函数

        1)子类没有定义拷贝赋值函数时:

                编译器为子类提供的缺省拷贝赋值函数内部,会自动调用基类的拷贝赋值函数

                复制该子类对象中的基类子对象。

        2)子类定义了拷贝赋值函数,但没有  显示调用  基类的拷贝赋值函数时:

                编译器不会塞任何操作,子类对象中的基类子对象得不到复制

        3)子类定义了拷贝赋值函数,同时  显示调用  了基类的拷贝赋值函数时:

                子类对象中的基类子对象得到复制

// ccons.cpp 子类的构造函数 和 析构函数
#include <iostream>
using namespace std;class Human {
public:Human( int age=0, const char* name="无名" ) : m_age(age),m_name(name) {//【int m_age=age;】定义m_age,初值为age//【string m_name(name);】定义m_name,利用m_name.string(name)cout << "Human类缺省构造函数被调用" << endl;}Human( const Human& that ) : m_age(that.m_age), m_name(that.m_name) { //【int m_age=that.m_age;】定义m_age,初值为that.m_age//【string m_name(that.m_name);】定义m_name,利用m_name.string(that.m_name)cout << "Human类拷贝构造函数被调用" << endl;}Human& operator=( const Human& that ) {// 编译器不会再拷贝赋值函数中塞任何操作cout << "Human类的拷贝赋值函数被调用" << endl;this->m_age = that.m_age;this->m_name = that.m_name; // this->m_name.operator=(that.m_name)-->string类的拷贝赋值函数return *this;}~Human() {cout << "Human类的析构函数被调用" << 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 Student : public Human {
public:void getinfo( ) {Human::getinfo();cout << ", 成绩:" << m_score << ", 评语:" << m_remark << endl;}
//  如果子类没有提供任何构造函数,编译器将提供一个无参的构造函数
/*  Student() {【Human();】定义基类子对象,利用 基类子对象.Human()【float m_score;】【string m_remark;】}*/Student( int age=0, const char* name="无名", float score=0.0, const char* remark="没有"): Human(age,name), m_score(score),m_remark(remark) {//【Human(age,name);】定义基类子对象,利用 基类子对象.Human(age,name)//【float m_score=score;】//【string m_remark(remark);】cout << "Student类的缺省构造函数被调用" << endl;}
//  如果子类没有提供析构函数,编译器将提供一个默认的析构函数
/*  ~Student() {对于类类型m_remark,利用m_remark.~string()对于基类子对象,利用基类子对象.~Human()释放 m_score/m_remark/基类子对象 本身所占内存空间}*/~Student() {cout << "Student类的析构函数被调用" << endl;// 对于类类型m_remark,利用m_remark.~string()// 对于基类子对象,利用基类子对象.~Human()// 释放 m_score/m_remark/基类子对象 本身所占内存空间}
//  如果子类没有提供拷贝构造函数,编译器将提供一个默认的拷贝构造函数
/*  Student( const Student& that ) {【Human(that);】定义基类子对象,利用 基类子对象.Human(that)-->Human类的拷贝构造函数【float m_score=that.m_score;】【string m_remark=that.m_remark;】}*/Student( const Student& that ) : Human(that), m_score(that.m_score), m_remark(that.m_remark) {//【Human(that);】定义基类子对象,利用 基类子对象.Human(that)-->Human类的拷贝构造函数//【float m_score=that.m_score;】//【string m_remark=that.m_remark;】cout << "Student类的拷贝构造函数被调用" << endl;}
//  如果子类没有提供拷贝赋值函数,编译器将提供一个默认的拷贝赋值函数
/*  Student& operator=( const Student& that ) {Human& rh = *this;rh = that; // rh.operator=(that)-->Human类的拷贝赋值函数this->m_score = that.m_score;this->m_remark = that.m_remark;return *this;}*/Student& operator=( const Student& that ) {// 编译器不会再拷贝赋值函数中塞任何操作cout << "Student类的拷贝赋值函数被调用" << endl;Human& rh = *this;rh = that; // rh.operator=(that)-->Human类的拷贝赋值函数this->m_score = that.m_score;this->m_remark = that.m_remark;return *this;}
private:float m_score;string m_remark;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {cout << "-----------------s1对象的创建信息-----------------------" << endl;Student s1(22,"张飞",88.5,"良好"); // 定义s1,利用s1.Student(22,"张飞",88.5,"良好")s1.getinfo();cout << "-----------------s2对象的创建信息-----------------------" << endl;Student s2 = s1; //(s1); 定义s2,利用s2.Student(s1)s2.getinfo();cout << "-----------------s3对象的创建信息-----------------------" << endl;Student s3;cout << "s3被赋值前--";s3.getinfo();s3 = s2; // s3.operator=(s2)cout << "s3被赋值后--";s3.getinfo();cout << "-----------------main will be over----------------------" << endl;return 0;
} // s1.~Student()   释放s1本身所占内存空间

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

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

相关文章

Javaweb之JDBC的详细解析

2. JDBC介绍(了解) 2.1 介绍 通过Mybatis的快速入门&#xff0c;我们明白了&#xff0c;通过Mybatis可以很方便的进行数据库的访问操作。但是大家要明白&#xff0c;其实java语言操作数据库呢&#xff0c;只能通过一种方式&#xff1a;使用sun公司提供的 JDBC 规范。 Mybatis…

从 MySQL 的事务 到 锁机制 再到 MVCC

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、事务 1.1 含义 1.2 ACID 二、锁机制 2.1 锁分类 2.2 隔离级别 三、MVCC 3.1 介绍 3.2 隔离级别 3.3 原理 四、总结 前…

【2023年度总结】 何其有幸 年岁并进 一元复始 万象更新

&#x1f319; 新年将至&#xff0c;万物更新&#xff0c;旧疾当愈。 今年极度焦虑。发生太多事情&#xff0c;做出很多改变。 自律。早起、拍照、运动、读书、学习、认识了很多厉害的朋友&#xff0c;尝试影响周围的人。这是我生活正向能量的来源。 学习。今年依然是把大量…

C#上位机与欧姆龙PLC的通信06---- HostLink协议(FINS版)

1、介绍 对于上位机开发来说&#xff0c;欧姆龙PLC支持的主要的协议有Hostlink协议&#xff0c;FinsTcp/Udp协议&#xff0c;EtherNetIP协议&#xff0c;本项目使用Hostlink协议。 Hostlink协议是欧姆龙PLC与上位机链接的公开协议。上位机通过发送Hostlink命令&#xff0c;可…

python实现Ethernet/IP协议的客户端(二)

Ethernet/IP是一种工业自动化领域中常用的网络通信协议&#xff0c;它是基于标准以太网技术的应用层协议。作为工业领域的通信协议之一&#xff0c;Ethernet/IP 提供了一种在工业自动化设备之间实现通信和数据交换的标准化方法。python要实现Ethernet/IP的客户端&#xff0c;可…

【Linux】socket基础API

目录 1. 创建socket&#xff08;TCP/UDP&#xff0c;客户端服务器&#xff09; 1.1 第一个参数——domain 1.2 第二个参数——type 1.3 第三个参数——protocol 2. 绑定socket地址&#xff08;TCP/UDP&#xff0c;服务器&#xff09; 2.1 字节序及转换函数 2.2 IP地址及…

消融实验(ablation study)——全网最全解读

消融实验&#xff08;ablation study&#xff09; 是什么优势与劣势案例总结 是什么 消融实验是一种科学研究方法&#xff0c;用于确定一个条件或参数对结果的影响程度。当研究者提出了一个新的方案或方法时&#xff0c;消融实验通过逐一控制一个条件或参数&#xff0c;来观察…

6个火爆全网的AI开源项目,用上月10万+

标题月10万可能说的有点夸张和含糊&#xff0c;10万具体指的是你可以利用这些开源项目实现&#xff1a; 访问量10万 收入10万 用户10万 …… 开源项目只是免费的工具&#xff0c;具体怎么实现还需要你根据自己需求去深入运营。这里只是给你推荐一些比较热门的开源项目&…

基于QT开发的温室气体数据记录软件

1、概述 温室气体分析仪数据记录软件用于实现温室气体分析仪数据的获取与存储&#xff0c;阀箱数据的获取与存储、冷阱数据的获取与存储、采样单元数据的获取与存储、阀箱和采样单元的远程操作以及系统功能的管理。其主操作界面如下&#xff1a; 上述软件界面分为2各区域&…

用html,js和layui写一个简单的点击打怪小游戏

介绍&#xff1a; 一个简单的打怪小游戏&#xff0c;点击开始游戏后&#xff0c;出现攻击按钮&#xff0c;击败怪物后可以选择继续下一关和结束游戏。 继续下一个怪兽的血量会增加5点&#xff0c;攻击按钮会随机变色。 效果图&#xff1a; html代码&#xff1a; <!DOCTYPE…

QDialog

属性方法 样式表 background-color: qlineargradient(spread:reflect, x1:0.999896, y1:0.494136, x2:1, y2:1, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));border: 1px groove rgb(232, 232, 232);border-radius: 20px; QDialog 的常用方法&#xff1a; e…

前端 js 基础(1)

js 结果输出 &#xff08;点击按钮修改文字 &#xff09; <!DOCTYPE html> <html> <head></head><body><h2>Head 中的 JavaScript</h2><p id"demo">一个段落。</p><button type"button" onclic…

基于PHP的校园代购商城系统

有需要请加文章底部Q哦 可远程调试 基于PHP的校园代购商城系统 一 介绍 此校园代购商城系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二 功能 …

2023/12/30 c++ work

定义一个Person类&#xff0c;私有成员int age&#xff0c;string &name&#xff0c;定义一个Stu类&#xff0c;包含私有成员double *score&#xff0c;写出两个类的构造函数、析构函数、拷贝构造和拷贝赋值函数&#xff0c;完成对Person的运算符重载(算术运算符、条件运算…

03 团队研究进一步详细介绍

一、印第安纳大学邢璐祎课题组 【团队网站】 https://www.xing-luyi.com/ 【团队介绍】 研究以形式化方法为特色&#xff0c;并保证系统中的安全性和隐私合规性&#xff0c;特别是物联网、云、移动和软件供应链。 【团队成果汇总】 物联网系统&#xff1a;[Oakland24][Se…

骑砍战团MOD开发(30)-游戏大地图map.txt

骑砍1战团mod开发-大地图制作方法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1rz4y1c7wH/ 一.骑砍游戏大地图 骑砍RTS视角游戏大地图 大地图静态模型(map.txt) 军团/城镇图标(module_parties.py). 骑砍大地图的战争迷雾和天气通过API进行管理和控制: # Weather-h…

分库分表之Mycat应用学习五

5 Mycat 离线扩缩容 当我们规划了数据分片&#xff0c;而数据已经超过了单个节点的存储上线&#xff0c;或者需要下线节 点的时候&#xff0c;就需要对数据重新分片。 5.1 Mycat 自带的工具 5.1.1 准备工作 1、mycat 所在环境安装 mysql 客户端程序。 2、mycat 的 lib 目录…

48、激活函数 - 梯度消失和梯度爆炸

简单介绍下梯度消失和梯度爆炸,这个不是重点,但是我觉得有必要再深入了解这个概念,以及很多激活函数为什么是可以防止梯度消失的。 梯度消失和梯度爆炸实际上是在神经网络训练过程中经常会遇到的两类问题,这两类问题都与梯度有关。 什么是梯度 在神经网络训练中,梯度是指…

深度学习 | Transformer模型及代码实现

Transformer 是 Google 的团队在 2017 年提出的一种 NLP 经典模型&#xff0c;现在比较火热的 Bert 也是基于 Transformer。Transformer 模型使用了 Self-Attention 机制&#xff0c;不采用 RNN 的顺序结构&#xff0c;使得模型可以并行化训练&#xff0c;而且能够拥有全局信息…

一年百模大战下来,有哪些技术趋势和行业真相逐渐浮出水面?

介绍 本人是独立开源软件开发者&#xff0c;参与很多项目建设&#xff0c;谈下感受。 ChatGPT开始AI生成元年&#xff0c;经历一年依然是第一。 LLaMA的巧合开启开源大模型浪潮。 名词解释 AIGC : AI-Generated Content 指利用人工智能技术&#xff08;生成式AI路径&#x…