C++ Day3

目录

一、类

【1】类

【2】应用实例

练习:

【3】封装

二、this指针

 【1】this指针的格式

【2】必须使用this指针的场合

三、类中的特殊成员函数

【1】构造函数

i)功能

ii)格式

iii)构造函数的调用时机

iv)构造函数允许函数重载

v)构造函数的初始化列表

1.格式:

2.必须使用初始化列表的情况:

2】析构函数

i)功能

ii)调用时机

iii)格式

iv)需要显性定义出析构函数的情况

【3】拷贝构造函数

i)功能

ii)格式

iii)调用时机

iv)深浅拷贝问题

【4】拷贝赋值函数

i)功能

ii)格式

作业:


一、类

面向对象的三大特征:封装、继承和多态

C++中封装是由类来实现的

C++中的类是由结构体演变而来的

结构体:变量和函数

类:成员属性(变量)、成员方法(函数)

【1】类

类中成员默认是private权限

class 类名
{
public:       ---->类外和类内都可以访问
    公有的成员变量/函数
private:      ---->类内可以访问,类外不能访问
    私有的成员变量/函数
protected:
    受保护的成员变量/函数    
};

【2】应用实例

#include <iostream>
using namespace std;

class Person
{
private:
    string name;
public:
    int age;
    int high;
    void set_name(string n);    //在类内声明函数
    void show()
    {
        cout << "name = "<< name << " age = "<<age << " high = "<<high << endl;
    }
};

int main()
{
    Person p1;       //实例化一个类对象p1
    p1.set_name("zhangsan");
    p1.age = 90;
    p1.high = 100;
    p1.show();

    return 0;
}

//类外实现
void Person::set_name(string n)
{
    name = n;
}

练习:

1、定义一个矩形类(Rectangle),包含私有成员长(length)、宽(width),定义成员函数:

设置长度: void set_len(int l);

设置宽度: void set_wid(int w);

获取长度: int get_len();

获取宽度: int get_wid();

显示周长和面积: void show();

#include <iostream>
using namespace std;

class Rec
{
    int length;
    int width;
public:
    //所有函数的类内声明
    void set_len(int l);
    void set_wid(int w);
    int get_len();
    int get_wid();
    void show();

};

void Rec::set_len(int l)
{
    length = l;
}
void Rec::set_wid(int w)
{
    width = w;
}
int Rec::get_len()
{
    return length;
}
int Rec::get_wid()
{
    return width;
}
void Rec::show()
{
    cout << "周长" << 2*(length+width) << endl;
    cout << "面积" << length*width << endl;
}
int main()
{
    Rec r1;    //实例化了一个Rec类的类对象r1
    r1.set_len(10);
    r1.set_wid(3);
    cout << "长:" << r1.get_len() << endl;
    cout << "宽:" << r1.get_wid() << endl;
    r1.show();
    return 0;
}

【3】封装

  1. 把某一事物的所有属性(变量)、行为(成员方法/成员函数),封装成一个整体,给私有的属性,提供公有的接口,以便于用户修改
  2. 类中成员都有访问权限(public,private,protected)
  3. 访问权限,是对于整个类而言的
  4. 类中同一访问权限,可以可以出现多次
  5. 类中默认是私有权限

二、this指针

this指针,是类内默认提供给非静态成员函数的指针,this指向,指向类对象本身,哪个类对象调用函数,this就指向哪一个类对象(谁调用函数this就指向谁)

 【1】this指针的格式

类名 *const this;  ----->不能修改指针指向

【2】必须使用this指针的场合

  1. 当成员函数的参数和类中成员属性同名时,需要使用this指向表明哪一个是类中的成员属性
  2. 拷贝赋值函数中,需要返回自身的引用,也需要使用this指针
#include <iostream>
using namespace std;

class Rec
{
    int length;
    int width;
public:
    //所有函数的类内声明
    void set_len(int length);
    void set_wid(int width);
    int get_len();
    int get_wid();
    void show();
};

void Rec::set_len(int length)
{
    this->length = length;
}

void Rec::set_wid(int width)
{
    this->width = width;
}

int Rec::get_len()
{
    return length;
}

int Rec::get_wid()
{
    return width;
}

void Rec::show()
{
    cout << "周长" << 2*(length+width) << endl;
    cout << "面积" << length*width << endl;
}
int main()
{
    Rec r1;    //实例化了一个Rec类的类对象r1
    Rec r2;
    r2.set_len(20);

    r1.set_len(10);
    r1.set_wid(3);
    cout << "长:" << r1.get_len() << endl;
    cout << "宽:" << r1.get_wid() << endl;
    r1.show();
    return 0;
}

三、类中的特殊成员函数

类中的特殊成员函数,程序员如果不手动写出来,系统会默认提供

一共有6个特殊的成员函数:构造函数、析构函数、拷贝构造函数、拷贝赋值函数,取地址运算符的重载和常取地址运算符的重复,C++11又提供了:移动构造、移动赋值函数

本文只有前四个

【1】构造函数

用于实例化类对象,系统会自动调用,系统自动提供的是无参构造

如果手动定义了构造函数,那么系统不会再提供一个无参构造

i)功能

实例化类对象时,申请空间使用的

ii)格式

类名(参数)
{
    函数体;
}

iii)构造函数的调用时机

栈区:什么时候实例化类对象,什么时候调用

在 C++ 中,对象可以在栈区实例化,这也被称为自动存储类对象。实例化对象时,会在栈上为对象分配内存空间,并调用对应的构造函数进行初始化。
对象的实例化和调用可以发生在不同的情况下:

1.在函数内部:当在函数内部定义一个类对象时,对象的实例化和构造函数的调用将发生在函数的作用域内。例如:

void foo() {
  MyClass obj;  // 实例化对象并调用构造函数
  // 函数内的其他操作
} // 函数结束,对象超出作用域,析构函数将会被调用


2.作为类的成员:如果一个类定义在另一个类中,并作为成员变量,那么对象的实例化和构造函数的调用将随着父类对象的实例化而发生。例如:

class ParentClass {
public:
  MyClass obj;  // 对象作为成员变量
};

int main() {
  ParentClass parentObj;  // 实例化父类对象,对象的实例化和构造函数调用都会发生
  // 其他操作
} // 父类对象超出作用域,析构函数将会被调用,对象的析构顺序与构造相反

需要注意的是,在栈上实例化的对象会在其所在的作用域结束时超出作用域,从而自动调用析构函数,释放对象占用的内存空间。这种自动释放内存的方式称为自动存储管理。

堆区:定义类的指针时,不调用构造函数。

什么时候new,什么时候调用 :应该在对象不再使用时调用对应的析构函数来释放内存,以避免内存泄漏。

iv)构造函数允许函数重载

  1. 系统默认提供一个无参构造函数
  2. 可以显性定义出有参构造,但是此刻系统不再提供默认的无参构造,还可以显性写出无参构造
  3. 构造函数是允许函数重载的
#include <iostream>
using namespace std;

class Stu
{
    string name;
    int age;
public:
    //定义Stu类的无参构造
    Stu()
    {
        cout << "Stu的无参构造" << endl;
    }
    //函数重载
    Stu(string name,int age)
    {
        this->name = name;
        this->age = age;
        cout << "Stu的有参构造" << endl;
    }
    Stu(string name)
    {
        this->name = name;
        cout << "Stu的对name的有参构造" << endl;
    }
};

int main()
{     
    Stu s1("zhangsan",18);  //栈区的类对象
    Stu *p;  //在栈区申请一个Stu*类型的指针
    p = new Stu("lisi");    //在堆区申请一个Stu的空间,会调用构造函数
    return 0;
}

v)构造函数的初始化列表

1.格式:

类型(形参):成员属性1(形参1),成员属性2(形参2),······{函数体内容} 

  1. 构造函数提供了初始化列表的机制,可以直接在函数体外执行初始化操作

  2. 初始化列表由:引出,每一个成员属性的值之间以,逗号分隔

2.必须使用初始化列表的情况:

  1. 形参和成员属性同名
  2. 类中有引用成员时,需要使用初始化列表
  3. 类中有const修饰的成员时
  4. 一个类中有另一个类的子对象时,需要使用初始化列表(如果两个类都有无参构造,是不需要写初始化列表)

 

//包含其他类的子对象
#include <iostream>
using namespace std;
class Per
{
    string name;
public:
    //Per提供的有参构造
    Per(string name)
    {
        this->name = name;
        cout << "Per的有参构造" << endl;
    }
    Per()
    {
        cout << "Per的无参构造" << endl;
    }
    //一个show函数,输出name
    void show()
    {
        cout << "Per中的name=" << name << endl;
    }
};

class Stu
{
    int score;
public:
    Per p1;    //Stu类中,包含另一个类的子对象,且另一个类只有有参构造函数
public:
    Stu(string name):p1(name)    //必须使用初始化列表,并且在初始化列表显性调用另一个类的构造函数
    {
        cout << "Stu的有参构造" << endl;
    }
    Stu()
    {
        cout << "Stu的无参构造" << endl;
    }
};

int main()
{
    Stu s1("zhangsan");
    //通过s1这个类对象,调用Per中的show函数
    s1.p1.show();

    Stu s2;
    return 0;
}

//同名或者是包含引用成员/const修饰的成员
class Stu
{
    string name;
    //int &age;     //类中有引用成员
    const int score;
public:
    //定义Stu类的无参构造
//    Stu()
//    {
//        cout << "Stu的无参构造" << endl;
//    }
    //函数重载,使用初始化列表的方式
    //初始化列表也可以解决形参和成员属性同名问题
    Stu(string name,int age):name(name),score(age)  //在函数体外给成员属性初始化
    {
        cout << "Stu的有参构造" << endl;
    }
    void show()
    {
        cout << name << " " << score << endl;
    }
};

int main()
{     
    Stu s1("zhangsan",18);  //栈区的类对象
    s1.show();
    Stu *p;  //在栈区申请一个Stu*类型的指针
    p = new Stu("lisi",20);    //在堆区申请一个Stu的空间,会调用构造函数
    return 0;
}

2】析构函数

析构函数,不支持函数重载,并且析构函数只有:~类名(){}

不需要传参数,public权限

i)功能

回收类对象的空间

ii)调用时机

栈区:类对象消亡时,自动调用

堆区:什么时候delete,什么时候调用析构函数

先构造的后析构,后构造的先析构

iii)格式

~类名()
{
    函数体;
}

iv)需要显性定义出析构函数的情况

  1. 类中有指针成员,并且指针成员指向堆区的空间
  2. 如果直接调用普通的析构函数,类对象消亡后,没有办法再去释放掉堆区的空间,会造成内存泄漏

#include <iostream>
using namespace std;

class Stu
{
    int *p;
public:
    Stu():p(new int)    //在不传参的情况下,给指针成员p用堆区的空间初始化
    {
        cout << "Stu无参构造" << endl;
    }

    Stu(int a):p(new int(a))   //在参数为整形变量的情况下,让p指向堆区申请的空间
    //但是把这篇空间的内容,用传过来的整形变量初始化
    {
        cout << "Stu的有参构造" << endl;
    }

    Stu(int *p)   //要求传过来的指针的值,一定是指向堆区空间
    {
        this->p = p;
        cout << "Stu传指针的有参构造" << endl;
    }

    ~Stu()
    {
        //在析构之前释放堆区的空间
        cout << "准备释放空间:" << p << endl;
        delete p;
        p = nullptr;
        cout << "Stu的析构函数" << endl;
    }
};

int main()
{
    Stu s1(90);
    return 0;
}

【3】拷贝构造函数

i)功能

使用已有的类对象,给类对象初始化的时候,自动调用拷贝构造函数

ii)格式

类名(类名 &other)
{
    函数体的内容;
}

拷贝构造函数,是一个构造函数,
函数名:类名
形参:其他类对象的引用

iii)调用时机

  1. 使用已有的类对象给新的类对象初始化
  2. 当函数的形参是一个类对象时,也会调用拷贝构造函数
  3. 当函数的返回值是一个类对象时,也会调用拷贝构造函数
#include <iostream>
using namespace std;
class Stu
{
    string name;
public:
    Stu()
    {
        cout << "Stu的无参构造" << endl;
    }
    Stu(string name)
    {
        this->name = name;
        cout << "Stu的有参构造" << endl;
    }
    Stu(Stu &other)   //Stu的拷贝构造函数,和无参构造以及有参构造构成函数冲澡
    {
        this->name = other.name;
        cout << "Stu的拷贝构造函数" << endl;
    }

    void show()
    {
        cout << name << endl;
    }
};
Stu fun(Stu s1)  //定义了一个函数fun,形参是一个类对象
{
    cout << "调用成功" << endl;
    return s1;
}
int main()
{
    Stu s1("zhangsan");
    cout << "s1:";
    s1.show();
    Stu s2 = s1;   //拷贝构造函数
    cout << "s2:";
    s2.show();
    fun(s2);
    return 0;
}

 

iv)深浅拷贝问题

什么情况下发生:类中存在指针成员时

深拷贝:两个指针成员指向不同空间,但是取*的结果是一致

浅拷贝:两个指针成员指向同一片空间

1、对同一片空间二次释放问题

2、两个类对象使用同一片空间,发生资源抢占问题

#include <iostream>
using namespace std;

class Stu
{
    int *p;
public:
    Stu():p(new int)    //在不传参的情况下,给指针成员p用堆区的空间初始化
    {
        cout << "Stu无参构造" << endl;
    }

    Stu(int a):p(new int(a))   //在参数为整形变量的情况下,让p指向堆区申请的空间
    //但是把这篇空间的内容,用传过来的整形变量初始化
    {
        cout << "Stu的有参构造" << endl;
    }
    Stu(int *p)   //要求传过来的指针的值,一定是指向堆区空间
    {
        this->p = p;
        cout << "Stu传指针的有参构造" << endl;
    }
    ~Stu()
    {
        //在析构之前释放堆区的空间
        cout << "准备释放空间:" << p << endl;
        delete p;
        p = nullptr;
        cout << "Stu的析构函数" << endl;
    }
    void show()
    {
        cout << "p=" << p << endl;
    }
    void set_p(int a)
    {
        *p = a;    //通过指针变量p,修改内存中的值
    }
    void show_p()
    {
        cout << *p << endl;  //通过指针变量,输出p指向的内存中的值
    }
    
    //拷贝构造函数
    Stu(Stu &other)
    {
        p = new int;  //手动让s2的指针p指向堆区的空间
        //实现深拷贝
        *p = *(other.p);
        cout << "Stu的拷贝构造函数" << endl;
    }
};
int main()
{
    Stu s1(90);    //会给s1的指针成员在堆区申请一片空间使用90初始化
    Stu s2 = s1;   //申请了一个Stu的类对象的空间,也实现了用s1的值初始化s2
    //左调右参
    //上面一行,调用了拷贝构造函数
    //使用了默认提供的拷贝构造,会造成指针成员,指向同一片空间的问题
//    cout << "s1:";
//    s1.show();
//    cout << "s2:";
//    s2.show();
    s1.show_p();
    s2.show_p();
    s1.set_p(101);
    s1.show_p();
    s2.show_p();

    return 0;
}

【4】拷贝赋值函数

i)功能

使用已有的类对象,给已有的类对象赋值的时候,会调用拷贝赋值函数。

ii)格式

类名 &operator=(const 类名 &other)
{
    函数体;
}

作业:

设计一个Per类,类中包含私有成员:姓名、年龄、指针成员身高、体重,再设计一个Stu类,类中包含私有成员:成绩、Per类对象 p1,设计这两个类的构造函数、析构函数和拷贝构造函数。

#include <iostream>

using namespace std;

class Per{
    string name;
    int age;
    float* height;
    float* weight;
public:
    //构造函数
    Per(string name,int age,float* height,float* weight)
    {
        this->name = name;
        this->age = age;
        this->height = height;
        this->weight = weight;
        cout << "Per的构造函数" << endl;
    }
    //析构函数
    ~Per()
    {
        delete height;
        delete weight;
        height = nullptr;
        weight = nullptr;
        cout << "Per的析构函数" << endl;
    }
    //拷贝构造函数
    Per(Per& other)
    {
        this->name = other.name;
        this->age = other.age;
        height = new float;
        *height = *(other.height);
        weight = new float;
        *weight = *(other.weight);
        cout << "Per的拷贝构造函数" << endl;
    }
    void show()
    {
        cout << name << endl;
    }
};

class Stu{
    float score;
    Per p1;
public:
    //必须使用初始化列表的情况:
    //形参和成员属性同名
    //类中有引用成员时,需要使用初始化列表
    //类中有const修饰的成员时
    //一个类中有另一个类的子对象时,需要使用初始化列表(如果两个类都有无参构造,是不需要写初始化列表)
    //Stu构造函数
    Stu(float score,string name,int age,float* height,float* weight):score(score),p1(name,age,height,weight)
    {
        cout<< "Stu的构造函数" << endl;
    }
    //析构函数
    ~Stu()
    {   
        cout << "Stu的析构函数" << endl;
    }
    //拷贝构造函数
    Stu(Stu& other):score(other.score),p1(other.p1)
    {
        cout << "Stu的拷贝构造函数" << endl;
    }
};

int main()
{
    float height = 175;
    float weight = 60;
    Per p("zhangsan",18,&height,&weight);
    Per p1 = p;
    Stu stu1(85.5,"lisi",18,&height,&weight);
    Stu stu2 = stu1;
    p.show();
    return 0;
}

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

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

相关文章

面试官:策略模式有使用过吗?我:没有......

面试官&#xff1a;策略模式有使用过吗&#xff1f;我&#xff1a;没有… 何为策略模式&#xff1f; 比如在业务逻辑或程序设计中比如要实现某个功能&#xff0c;有多种方案可供我们选择。比如要压缩一个文件&#xff0c;我们既可以选择 ZIP 算法&#xff0c;也可以选择 GZIP…

【云计算】Docker特别版——前端一篇学会

docker学习 文章目录 一、下载安装docker&#xff08;一&#xff09;Windows桌面应用安装&#xff08;二&#xff09;Linux命令安装 二、windows注册登录docker三、Docker的常规操作(一)、基本的 Docker 命令(二)、镜像操作(三)、容器的配置(四)、登录远程仓库 四、镜像管理(一…

SIP桌面式对讲主机 井下通信广播sip寻呼话筒

SV-8003VP是我司的一款SIP桌面式对讲主机&#xff0c;具有10/100M以太网接口&#xff0c;配置了麦克风输入和扬声器输出&#xff0c;还配置多达22个按键和2.8英寸液晶显示屏&#xff0c;可以配合SIP服务器使用。SV-8003VP网路寻呼话筒可以通过麦克风或者本地线路输入对SIP终端进…

CLIP(Contrastive Language-Image Pre-training)

《Learning Transferable Visual Models From Natural Language Supervision》 从自然语言监督中学习可迁移的视觉模型 贡献:利用自然语言信号监督,打破了固定类别的范式。 方法简单,效果好。从文本中得到监督信号,引导视觉分类的任务。 它是一个 zero-shot 的视觉分类…

MyBatis进阶:告别SQL注入!MyBatis分页与特殊字符的正确使用方式

目录 引言 一、使用正确的方式实现分页 1.1.什么是分页 1.2.MyBatis中的分页实现方式 1.3.避免SQL注入的技巧 二、特殊字符的正确使用方式 2.1.什么是特殊字符 2.2.特殊字符在SQL查询中的作用 2.3.如何避免特殊字符引起的问题 2.3.1.使用CDATA区段 2.3.2.使用实体引…

AndroidStudio升级后总是Read Time Out的解决办法

AndroidStudio升级后在gradle的时候总是Time out&#xff0c;遇到过多次&#xff0c;总结一下解决办法 1、gradle下载超时 在工程目录../gradle/wrapper/gradle-wrapper.properties中找到gradle版本的下载链接&#xff0c;如下图&#xff1a; 将其复制到迅雷里下载&#xff0…

利用 XGBoost 进行时间序列预测

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建3D应用场景 XGBoost 应用程序的常见情况是分类预测&#xff08;如欺诈检测&#xff09;或回归预测&#xff08;如房价预测&#xff09;。但是&#xff0c;也可以扩展 XGBoost 算法以预测时间序列数据。它是如何工作的&#xf…

2023 百度翻译 爬虫 js逆向 代码

js代码&#xff1a; const jsdom require("jsdom"); const {JSDOM} jsdom; const dom new JSDOM(<!DOCTYPE html><p>Hello world</p>); window dom.window; document window.document; XMLHttpRequest window.XMLHttpRequest;function n(t,…

机器学习笔记之优化算法(十六)梯度下降法在强凸函数上的收敛性证明

机器学习笔记之优化算法——梯度下降法在强凸函数上的收敛性证明 引言回顾&#xff1a;凸函数与强凸函数梯度下降法&#xff1a;凸函数上的收敛性分析 关于白老爹定理的一些新的认识梯度下降法在强凸函数上的收敛性收敛性定理介绍结论分析证明过程 引言 本节将介绍&#xff1a…

安装Node(脚手架)

目录 一&#xff0c;安装node&#xff08;脚手架&#xff09;1.1&#xff0c; 配置vue.config.js1.2&#xff0c; vue-cli3x的目录介绍1.3&#xff0c; package.json 最后 一&#xff0c;安装node&#xff08;脚手架&#xff09; 从官网直接下载安装即可&#xff0c;自带npm包管…

HBuilderX学习--运行第一个项目

HBuilderX&#xff0c;简称HX&#xff0c;是轻如编辑器、强如IDE的合体版本&#xff0c;它及轻巧、极速&#xff0c;强大的语法提示&#xff0c;提供比其他工具更优秀的vue支持大幅提升vue开发效率于一身(具体可看官方详细解释)… 一&#xff0c;HBuilderX下载安装 官网地址 …

【SVN内网穿透】远程访问Linux SVN服务

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

酷开科技大屏营销,锁定目标人群助力营销投放

近日&#xff0c;中科网联发布《2023年中国家庭大屏白皮书》&#xff0c;数据显示智能电视近三年内使用人群增长平稳。全国4.94亿家庭户中&#xff0c;智能大屏渗透率近九成。不仅如此&#xff0c; CCData研究预测&#xff0c;2025年中国智能电视渗透率将达到95%以上。这与三年…

stm32之16.外设定时器——TIM3

----------- 源码 void tim3_init(void) {NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//使能TIM3的硬件时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//配置TIM3的定时时间TIM_TimeBaseStructure.TIM_Period 10000-1…

基于GRU门控循环网络的时间序列预测matlab仿真,对比LSTM网络

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 LSTM: GRU 2.算法运行软件版本 matlab2022a 3.部分核心程序 %构建GRU网络模型 layers [ ...sequenceInputLayer(N_feature)gruLayer(N_hidden)f…

jupyter notebook 插件nbextensions的安装

安装步骤&#xff1a; 1、打开 jupyter notebook&#xff0c;新建一个 python 文件&#xff1b; 2、 分别输入以下代码&#xff0c;然后运行&#xff0c;出现 warning 不影响使用&#xff0c;如果出现 errors&#xff0c;则说明下载有问题&#xff1a; !python -m pip install…

【VR】SteamVR2.0的示例场景在哪里

&#x1f4a6;本专栏是我关于VR开发的笔记 &#x1f236;本篇是——在哪里可以找到SteamVR2.0的示例场景 SteamVR2.0的示例场景在哪里 1. 逐步打开方式2. 快速打开方式 1. 逐步打开方式 Assets——SteamVR——InteractionSystem——Samples——>Interactions_Example 2. 快…

Grounded Language-Image Pre-training论文笔记

Title&#xff1a;Grounded Language-Image Pre-training Code 文章目录 1. 背景2. 方法&#xff08;1&#xff09;Unified Formulation传统目标检测grounding目标检测 &#xff08;2&#xff09;Language-Aware Deep Fusion&#xff08;3&#xff09;Pre-training with Scala…

Unity 结构少继承多组合

为什么不推荐使用继承&#xff1f; 继承是面向对象的四大特性之一&#xff0c;用来表示类之间的 is-a 关系&#xff0c;可以解决代码复用的问题。虽然继承有诸多作用&#xff0c;但继承层次过深、过复杂&#xff0c;也会影响到代码的可维护性。所以&#xff0c;对于是否应该在…

Qt双击某一文件通过自己实现的程序打开,并加载文件显示

双击启动 简述方法一方法二注意 简述 在Windows系统中&#xff0c;双击某类扩展名的文件&#xff0c;通过自己实现的程序打开文件&#xff0c;并正确加载及显示文件。有两种方式可以到达这个目的。 对于系统不知道的扩展名的文件&#xff0c;第一次打开时&#xff0c;需要自行…