c++_09_继承

news2024/11/28 3:45:14

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; // ok
        foo();     // ok
        m_b = 200; // ok
        bar();     // 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; // 12

    Derived d; // 子类对象--> |基类子对象|m_d| --> |m_a m_b m_c|m_d|
    cout << "子类对象d的大小:" << sizeof(d) << endl; // 16
    return 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隐藏,但可以利用作用域限定符强制调用基类的foo
        bar(); // 子类的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; // ok
        foo();     // ok
        m_b = 200; // ok
        bar();     // ok, 以上四行代码证明子类内部可以直接访问基类的公有和保护成员
//      m_c = 300; // error
//      hum();     // error,以上两行代码证明子类内部不可以直接访问基类的私有成员
    }
private:
    int m_d;
};
// 模拟类的设计者(类库、别人设计的类、自己设计的类)
// --------------------------------
// 模拟用户(使用类的人)
int main( void ) {
    Derived d; // 利用子类对象在类外访问基类的成员,编译器需要查看这些成员在子类中的重新标记
    d.m_a = 1000; // ok
    d.foo();      // ok
//    d.m_b = 2000; // error
//    d.bar();      // error
//    d.m_c = 3000; // error
//    d.hum();      // error
    return 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; // ok
        foo();     // ok
        m_b = 200; // ok
        bar();     // 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();      // error
    return 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; // ok
        foo();     // ok
        m_b = 200; // ok
        bar();     // 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();      // error
    return 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; // ok
    d.foo();      // ok,只有在公有继承下,子类对象在类外可以访问基类的公有成员
    d.Base::foo();// ok
    return 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; // 36

    Student s; // |基类子对象|m_no| --> |m_age m_name|m_no|
    cout << "子类对象s的大小:" << sizeof(s) << endl; // 40

    Human* 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.coloradmin.cn/o/1349069.html

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

相关文章

MySql——1146 - Table‘mysql.proc‘doesn‘t exit是这个

项目场景&#xff1a; 做自己的小项目需要连接mysql数据库 问题描述 点击数据库时报错 1146 - Table’mysql.proc’doesn’t exit 原因分析&#xff1a; 误删原生的mysql数据库 解决方案&#xff1a; 重新安装装部署mysql就好了 注意不要轻易删除原生的东西

基于Java在线商城系统设计实现(源码+部署文档+讲解视频)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌&#x1f345; 文末获取源码联系 &#x1f345;&#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

qt图像绘制QPainter

QPainter 以下是一些常用的 Qt::PenStyle 枚举值&#xff1a; Qt::NoPen&#xff1a;无线条。Qt::SolidLine&#xff1a;实线。Qt::DashLine&#xff1a;虚线&#xff0c;由短划线组成。Qt::DotLine&#xff1a;点线&#xff0c;由点组成。Qt::DashDotLine&#xff1a;点划线&…

HarmonyOS 实践之应用状态变量共享

平时在开发的过程中&#xff0c;我们会在应用中共享数据&#xff0c;在不同的页面间共享信息。虽然常用的共享信息&#xff0c;也可以通过不同页面中组件间信息共享的方式&#xff0c;但有时使用应用级别的状态管理会让开发工作变得简单。 根据不同的使用场景&#xff0c;ArkTS…

SELinux 基本原理

本文讲述 SELinux 保护安全的基本原理 首发公号&#xff1a;Rand_cs 安全检查顺序 不废话&#xff0c;直接先来看张图 当我们执行系统调用的时候&#xff0c;会首先对某些错误情况进行检查&#xff0c;如果失败通常会得到一些 error 信息&#xff0c;通过查看全局变量 errno …

多模态大模型的前世今生

1 引言 前段时间 ChatGPT 进行了一轮重大更新&#xff1a;多模态上线&#xff0c;能说话&#xff0c;会看图&#xff01;微软发了一篇长达 166 页的 GPT-4V 测评论文&#xff0c;一时间又带起了一阵多模态的热议&#xff0c;随后像是 LLaVA-1.5、CogVLM、MiniGPT-5 等研究工作…

matalb实践(十二):减肥

1.题目 2.解答 2.1模型假设 1.体重增加正比于吸收的热量&#xff0c;平均每8000kcal增加体重1kg 2.身体正常代谢引起的体重减少正比于体重&#xff0c;每周每千克体重消耗热量一般在200kcal至320kcal之间&#xff0c;且因人而异&#xff0c;这相当于体重70kg的人每天消耗2000k…

Feign远程调用丢失请求头问题处理--异步任务执行远程请求线程丢失请求属性问题处理

在关于Feign远程调用丢失请求头问题处理中解决了远程调用发送请求丢失老请求中请求头的问题。A方法接收浏览器中的请求&#xff0c;B方法是A方法中嵌套方法用来发送Feign远程调用。如果B方法是在异步任务CompletableFuture.runAsync(()->{},Executor)中执行并启用线程池分配…

C++多态性——(1)初识多态

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 苦难和幸福一样&#xff0c;都是生命盛…

HarmonyOS 组件通用属性之通用事件 文档参数讲解(触摸事件)

好 本文 我们来说说触摸事件 字面意思也非常好理解 就是我们手机手指触摸物体触发 我们先在编辑器组件介绍中 找到这个东西的基本用法 Button("跳转").onTouch((event: TouchEvent) > {})最明显的就是 event 的类型变了 点击事件的是 ClickEvent 而这里是 Touc…

【教3妹学编程-算法题】经营摩天轮的最大利润

3妹&#xff1a;“打个中国结&#xff0c;再系个红腰带&#xff0c; 愿善良的人们天天好运来, 你勤劳生活美, 你健康春常在, 你一生的忙碌为了笑逐颜开。” 2哥 : 3妹&#xff0c;元旦快乐啊。 3妹&#xff1a;2哥元旦快乐~。 2哥&#xff1a;祝新的一年&#xff0c;3妹技术突飞…

数据结构与算法之美学习笔记:42 | 动态规划实战:如何实现搜索引擎中的拼写纠错功能?

目录 前言如何量化两个字符串的相似度&#xff1f;如何编程计算莱文斯坦距离&#xff1f;如何编程计算最长公共子串长度&#xff1f;解答开篇 前言 本节课程思维导图&#xff1a; 利用 Trie 树&#xff0c;可以实现搜索引擎的关键词提示功能&#xff0c;这样可以节省用户输入搜…

easyx的窗口函数

文章目录 前言一、EasyX的颜色二、EasyX的坐标和设备1&#xff0c;EasyX的坐标2&#xff0c;EasyX的设备 三、窗口函数1&#xff0c;初始化窗口函数2&#xff0c;关闭绘图窗口3&#xff0c;设置窗口背景板颜色4&#xff0c;清空绘图设备 前言 easyx是针对c的图形库&#xff0c;…

从0到1入门C++编程——02 通讯录管理系统

文章目录 一、创建结构体及菜单显示二、添加联系人三、显示联系人四、删除联系人五、查找联系人六、修改联系人七、清空联系人八、退出通讯录 本文通过C实现一个通讯录管理系统&#xff0c;系统要实现的功能如下。 1、添加联系人&#xff1a;向通讯录中添加新人&#xff0c;信息…

老胡的周刊(第122期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 movie-web[2] 开源可自部署的简约在线电影搜…

【MATLAB】鲸鱼算法优化混合核极限学习机(WOA-HKELM)时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 鲸鱼算法优化混合核极限学习机&#xff08;WOA-HKELM&#xff09;是一种时序预测算法&#xff0c;它结合了鲸鱼算法和混合核极限学习机&#xff08;HKELM&#xff09;的优点。以下是该算法…

解锁React魔法门:高效项目开发工作流揭秘

你好&#xff0c;我是坚持分享干货的 EarlGrey&#xff0c;翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助&#xff0c;请关注我&#xff0c;一起向上进击。 创作不易&#xff0c;希望大家给一点鼓励&#xff0c;把公众号设置为…

2024年PMP考试新考纲-PMBOK第七版-【模型、方法和工件】真题解析(2)

今天我们继续来看第七版PMBOK第四部分【模型、方法和工件】这个章节相关的真题。 实际上在做题的时候&#xff0c;可能有的小伙伴会发现&#xff0c;这部分和第六版PMBOK中散落在各个知识领域的题目很相似。没错&#xff01;在之前版本的PMBOK中&#xff0c;很经典的框架是每个…

2.1 DFMEA步骤一:策划和准备

2.1.1 目的 设计FMEA的“策划和准备”步骤旨在确定将要执行的FMEA类型,以及根据进行中的分析类型(如系统、子系统或组件)明确每个FMEA的范围。设计FMEA(DFMEA)的主要目标包括: 项目识别项目计划:涵盖目的、时间安排、团队、任务和工具(5T)分析边界:界定分析的范围,…

LLM应用的分块策略

每日推荐一篇专注于解决实际问题的外文&#xff0c;精准翻译并深入解读其要点&#xff0c;助力读者培养实际问题解决和代码动手的能力。 欢迎关注公众号 原文标题&#xff1a;Chunking Strategies for LLM Applications 原文地址&#xff1a;https://www.pinecone.io/learn/c…