c++ 设计模式 的课本范例(上)

( 0 ) 这里补充面向对象设计的几个原则:
开闭原则OCP : 面向增补开放,面向代码修改关闭。其实反映到代码设计上就是类的继承,通过继承与多态,可以不修改原代码,又增加新的类似的功能。
依赖倒置原则 Dependency Inversion Principle DIP : 面向父类的虚函数编程,可以节省代码量与减少重复。

(1) 框架设计模式 model mode : 算法的框架不变,算法的细节可以改变。主要依赖多态。

class Player
{
protected:int life;int magic;int attack;virtual void effect_self() {}virtual void effect_enemy() {}virtual bool can_burn() = 0;
public:Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack) {}virtual Player(){}void play_effect_burn() { cout << "play_effect_burn\n"; }void burn()    // 模板模式:算法的框架不变,细节可以变{if (can_burn()){effect_enemy();effect_self();play_effect_burn();}}
};class Fighter : public Player
{
public:Fighter() : Player(100, 100, 50) {}void effect_self() override { this->life -= 30; }void effect_enemy() override { cout << "敌人被燃烧 40 血\n"; }bool can_burn() override { if (this->life >= 40)  return true;else                   return false; }
};

(2)简单工厂模式:不要直接使用 new A() 创建对象,一旦对类 A 增删和修改参数,会紧耦合,牵一发动全身,用一个函数集中使用 new A ,返回创建好的对象,如同工厂批量生产产品一样。对构造对象时 的修改也限制在工厂方法里。

class Player  // 角色父类
{
protected:int life;int magic;int attack;public:Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack) {}virtual Player(){}
};class Fighter : public Player   // 战士
{
public:Fighter() : Player(100, 100, 50) {}
};class Master : public Player  // 法师
{
public:Master() : Player(50, 300, 150) {}
};class Create   // 把 new 语句集中在产生对象的函数里,减小代码以后升级时需要修改的范围
{
public:static Player* createPlayer(string str){if(str == "fighter") return new Fighter();else if(str == "master")return new Master();}	
};int main()
{auto pFighter = Create::createPlayer("fighter");auto pMaster = Create::createPlayer("master");delete pFighter;delete pMaster;return 0;
}

但工厂函数里的 if 选择,如果要创建新类,会修改原代码。面向对象的 OCP 原则:更新代码时,尽量追加新代码,而不是修改原代码,向增加开放,向修改关闭。如此引出工厂模式。

(3) 工厂模式:符合 OCP 规则的 用工厂方式生产对象:

class Player  // 角色父类
{
protected:int life;int magic;int attack;public:	Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack) {}virtual Player(){}
};class Fighter : public Player   // 战士
{
public:	Fighter(int life, int magic, int attack) : Player(life , magic , attack) {}
};class Master : public Player  // 法师
{
public:	Master(int life, int magic, int attack) : Player(life, magic, attack) {}
};class Create   // 制造生产对象的虚基类
{
public:	virtual Player* createPlayer() = 0;virtual Create(){}
};class Create_Fighter : public Create  // 对应对象的工厂类
{
public:	Player* createPlayer() override { return new Fighter(50,50,50); }
};class Create_Monster : public Create
{
public:	Player* createPlayer() override { return new Master(60,60,60); }
};int main()
{auto pFactFight = new Create_Fighter();auto pFighter = pFactFight->createPlayer();auto pFactMaster = new Create_Monster();auto pMastr = pFactMaster->createPlayer();delete pFactFight;delete pFactMaster;delete pFighter;delete pMastr;return 0;
}

(4) 抽象工厂模式,比工厂模式密度更高的生产对象的模式:一个工厂类包含了多个生产对象的函数:

class Player  // 角色父类
{
protected:int life;int magic;int attack;public:	Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack) {}virtual Player(){}
};class Fighter_Land : public Player   // 陆上战士 
{
public:	Fighter_Land(int life, int magic, int attack) : Player(life , magic , attack) {}
};class Fighter_Sea : public Player   // 海洋战士
{
public:	Fighter_Sea(int life, int magic, int attack) : Player(life, magic, attack) {}
};class Master_Land : public Player  // 陆上法师 ,游戏新版本,不同的游戏场景
{
public:	Master_Land (int life, int magic, int attack) : Player(life, magic, attack) {}
};class Master_Sea : public Player  // 海洋法师
{
public:	Master_Sea(int life, int magic, int attack) : Player(life, magic, attack) {}
};class Create   // 制造生产对象的虚基类
{
public:	virtual Player* createPlayer() = 0;virtual Player* createMaster() = 0;virtual Create(){}
};class Create_Land : public Create  // 不同场景下的角色生产工厂
{
public:Player* createPlayer() override { return new Fighter_Land(10,10,10); }Player* createMaster() override { return new Master_Land(20,20,20); }
};class Create_Sea : public Create
{
public:Player* createPlayer() override { return new Fighter_Sea(10,10,10); }Player* createMaster() override { return new Master_Sea(20, 20, 20); }
};int main()
{auto pCreate_Land = new Create_Land();auto pFighter_Land = pCreate_Land->createPlayer();;auto PMaster_Land = pCreate_Land->createMaster();auto pCreate_Sea = new Create_Sea();auto pFighter_Sea = pCreate_Sea->createPlayer();auto pMaster_Sea = pCreate_Sea->createMaster();delete pCreate_Land; delete pFighter_Land; delete PMaster_Land;delete pCreate_Sea;  delete pFighter_Sea;  delete pMaster_Sea;return 0;
}

工厂模式不要忘记 delete 这些指针,包括在堆区创建的工厂对象和工厂生产的类对象,都要在最后 delete 掉,释放掉。

(5) 原型模式:通过对象原型来产生新的对象。主要是把工厂类里生产对象的方法转移到了对象类里。 clone() 函数

class Player  // 角色父类
{
protected:int life;int magic;int attack;public:	Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack) {}Player(const Player& p) :life(p.life), magic(p.magic), attack(p.attack) {}~Player() {}    // 父类应有的虚析构函数virtual Player* clone() = 0;
};class Fighter_Land : public Player   // 陆上战士 
{
public:	Fighter_Land(int life, int magic, int attack) : Player(life , magic , attack) {}Fighter_Land(const Fighter_Land& p) : Player(p) {}Player* clone() override { return new Fighter_Land(* this); }
};

(6) 建造者模式( builder ):与工厂模式的区别是:工厂模式生产的对象简单,可以直接交付。若生产的对象复杂,比如还要组装游戏角色,加工后再返回对象 ; 或者把前端页面里的报表(有头部,主体和尾部)组合转换为 txt 、 xmL、json 格式交给后端处理。只有经过对对象的加工处理,才可以得到复杂的对象,就是建造者模式,建造二字突出其是要创建复杂对象,突出建造的复杂性。而且可以把加工建造对象的过程单独拎出来实现批量建造。

class Player  // 角色父类
{
protected:int life;int magic;int attack;
public:virtual ~Player() {}    // 父类应有的虚析构函数Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack) {}
};class Fighter : public Player   // 战士 
{
public:Fighter(int life, int magic, int attack) : Player(life, magic, attack) {}
};class Create   // 制造生产对象的虚基类
{
protected:Player* ptrPlayer;
public:virtual ~Create() { if (ptrPlayer) delete ptrPlayer; }  // 这里析构函数要释放指针Player* getPlayer() { return std::exchange(ptrPlayer, nullptr); }virtual void loadHead() = 0;virtual void loadTrunk() = 0;virtual void loadFeet() = 0;
};class Create_Fight : public Create  // 制造战士的工厂
{
public:Create_Fight() :Create() { ptrPlayer = new Fighter(10, 10, 10); }void loadHead()  override { cout << "load head\n"; }void loadTrunk() override { cout << "load trunk\n"; }void loadFeet()  override { cout << "load feet\n"; }
};class Assemble
{
private:Create* ptrCreate;
public:Assemble(Create* t) : ptrCreate(t) {}Player* assemble(){ptrCreate->loadHead();ptrCreate->loadTrunk();ptrCreate->loadFeet();return ptrCreate->getPlayer();}
};int main()
{auto pFighterCreate = new Create_Fight();auto pAssemble = new Assemble(pFighterCreate);auto pFight = pAssemble->assemble();delete pFighterCreate;  // 经测试没有内存泄露delete pAssemble;delete pFight;return 0;
}

本模式另举一例:根据前端页面的报表来构造完整的数据报表,供后端使用:

在这里插入图片描述

相关代码如下:

class Head  // 日报头
{
private:string department;string date;
public:Head(const string& dep, const string& time) : department(dep), date(time) {}string& getDepart() { return department; }string& getDate()   { return date; }
};class Content  // 日报内容
{
private:string content;double totalTime;
public:Content(const string& cont, const double& time) : content(cont), totalTime(time) {}string& getContent() { return content; }double& getTotalTime() { return totalTime; }
};class Foot   // 日报尾
{
private:string name;
public:Foot(const string& name) :name(name) {}string& getName() { return name; }
};class Builder   // 建造完整的日报
{
protected:string result;
public:virtual ~Builder() { }virtual void buildHead( Head * ) = 0;virtual void buildCont(vector<Content* >& vec) = 0;virtual void buildFoot(Foot*) = 0;string& getRes() { return result; }  // 返回左值引用
};class Txt_builder : public Builder  // 建造 txt 型日报
{
public:void buildHead(Head* pHead) override{		result += pHead->getDepart() + " , " + pHead->getDate() + "\n";}void buildCont(vector<Content* >& vec) override{for (auto iter = vec.begin(); iter != vec.end(); iter++){ostringstream oss;  // 此对象在每次 for 循环中都会被创建和释放,oss << (*iter)->getTotalTime();  // 所以输入到 oss 中的内容并不会积累。result += (*iter)->getContent() + " ,花费小时:" + oss.str() + '\n';}}void buildFoot(Foot* pFoot) override{result += "报告人:" + pFoot->getName() + '\n';}
};class Assemble   // 本类可以组装各种日报: txt 、 xmL 、 Json
{
private: Builder* builder;
public:Assemble(Builder* builder) : builder(builder) {}string& assemble(Head * head , vector<Content * >& vec , Foot * foot){builder->buildHead(head);builder->buildCont(vec);builder->buildFoot(foot);return builder->getRes();}
};int main()
{Head head("研发部" , "7.13");Content conA("分析文档"  , 3.5);Content conB("选定语言"  , 0.5);Foot foot("zhangwuji");vector<Content*> vecCont{&conA , &conB};Txt_builder txtBuilter;Assemble assemble(&txtBuilter);auto strResult = assemble.assemble(&head , vecCont , &foot);cout << strResult << endl;return 0;
}

这里给出测试结果:

在这里插入图片描述

(7) 策略模式 Strategy 。类似于框架模式:策略的框架不变,实现细节会变,但比框架模式更复杂一点。还是以上面的游戏角色为例,战士和法师都可以采用回血策略,回血策略又可以分为小药回小血,中药回中血,大药回大血的不同具体策略,甚至随着游戏扩展,还有新的策略,或修订原有的策略。

class Strategy;  // 前置声明,否则编译报错
class Player;class Strategy
{
public:virtual ~Strategy() {}virtual void heal(Player*) = 0;
};class Player  // 角色父类
{
protected:int life;int magic;int attack;Strategy* pStrategy ;
public:	virtual ~Player() {}    // 父类应有的虚析构函数Player(int life, int magic, int attack) : life(life), magic(magic), attack(attack), pStrategy(nullptr){}int getLife() { return life; }void setLife(int t) { life = t; }void setStrategy(Strategy* p) { pStrategy = p; }void heal() { pStrategy->heal(this); }
};class Fighter : public Player   // 战士 
{
public:	Fighter(int life, int magic, int attack) : Player(life , magic , attack) {}
};class Master : public Player  // 法师 
{
public:	Master (int life, int magic, int attack) : Player(life, magic, attack) {}
};class Strategy_Small_Medi : public Strategy
{
public:void heal(Player* ptr) { ptr->setLife( ptr->getLife() + 200 ); }
};class Strategy_Middle_Medi : public Strategy
{
public:void heal(Player* ptr) { ptr->setLife(ptr->getLife() + 300); }
};int main()
{Fighter fight(100, 100, 100);Strategy_Small_Medi small;fight.setStrategy(&small);fight.heal();return 0;
}

(8) 观察者模式observer , 也叫 发布–订阅模式,Publish – Subscribe 。 订阅者就是观察者。因为发布者的信息要群发,所以就要注意提升遍历数据库时的效率,尽可能快速的把消息发布给所有的订阅者。重在良好组织所有对象的存储方式,加快对订阅者的遍历速度: 比如 map 容器的遍历就比 list 要快。

class Player;class Manager   // 管理,充当数据库的角色,管理玩家角色的组信息
{
public:virtual ~Manager() {}virtual void joinFamily(Player *) = 0;virtual void leaveFamily(Player*) = 0;virtual void notify(Player* , const string & ) = 0;
};class Player  // 角色父类
{
protected:int id;int familyID;string name;
public:	virtual ~Player() {}    // 父类应有的虚析构函数Player(int id, const string& name) : id(id), name(name) { familyID = -1; }void setFamily(int t) { familyID = t; }int getFamily() { return familyID; }void speak(const string& str, Manager* maga) { maga->notify(this, str); }void getNotice( Player * player , const string & str ) {cout << name << "  的电脑显示  " << player->name << "  的信息: " << str << "\n\n";}
};class Fighter : public Player   // 战士 
{
public: 	Fighter(int id, const string & name) : Player(id, name) {}
};class Master : public Player   // 法师
{
public:  	Master(int id, const string& name) : Player(id, name) {}
};class Manager_Fighter : public Manager // 采用默认的构造函数
{
private:map<int, list<Player*>> allFamily;  // 管理所有的有家族的角色,以家族的方式管理角色
public:virtual void joinFamily(Player* player) override{int familyID = player->getFamily();if (familyID != -1)  // 要插入家族树的角色必须具有有效的家族 id {auto iter = allFamily.find(familyID);if (iter != allFamily.end())  // 该家族已在家族树中iter->second.push_back(player);else             // 出现了新的家族,要先把家族链表 list 创建并插入 map 中{list<Player*> list;allFamily.insert(make_pair(familyID , list));allFamily[familyID].push_back(player);  // 理解难度在于 STL 库容器中 map 的成员方法的使用}}}virtual void leaveFamily(Player * player) override{int familyID = player->getFamily();if (familyID != -1){auto iter = allFamily.find(familyID);if (iter != allFamily.end())allFamily[familyID].remove(player);  // list 允许插入相同的节点。也会被全部删除。当然指针是不会相同的}}virtual void notify(Player* speaker, const string& str) override{int familyID = speaker->getFamily();if (familyID != -1){auto iter = allFamily.find(familyID);if (iter != allFamily.end())for (auto iterList = iter->second.begin(); iterList != iter->second.end(); iterList++)(*iterList)->getNotice(speaker, str);}}
};int main()
{Fighter zhang(10, "张三");Fighter zhao(11, "赵四");Fighter wang(12, "王五");Fighter ma(13, "马虎");Manager_Fighter managerFight;zhang.setFamily(100);zhao.setFamily(100);wang.setFamily(100);ma.setFamily(200);managerFight.joinFamily(&zhang);managerFight.joinFamily(&zhao);managerFight.joinFamily(&wang);managerFight.joinFamily(&ma);zhang.speak("Hello , i love you !!" , &managerFight);return 0;
}

以下给出测试结果:

在这里插入图片描述

(9) 装饰器模式 decorator 。比如显示器绘图,绘制控件 ,比如带框的列表框,就要先绘制列表框,再给其加框;绘制带滚动条的列表框,就要先绘制列表框,再绘制滚动条。有绘图的先后顺序。类继承不恰当时候,比如子类不需要父类的所有功能,就可以考虑类组合,一个类的数据成员是另一个类,以获得更灵活强大的功能。

class Control    // 控件基类
{
public:~Control() {}virtual void draw() = 0 ;
};class Control_List : public Control   // 列表控件
{
public: virtual void draw() override { cout << " 列表框绘制\n\n"; }};class Decorator : public Control  // 装饰器基类 : 其先要绘制被修饰的控件。但带修饰的控件依然可以再被修饰。
{
private: Control* ptrControl;  // 被修饰的控件对象
public:Decorator(Control* p) : ptrControl(p) {}virtual void draw() override { ptrControl->draw() ; }  // 作为装饰类的基类的 draw()方法
};class Decorator_border : public Decorator  // 装饰器:边框
{
public:Decorator_border(Control* p) : Decorator(p) {}virtual void draw() override{Decorator::draw();  // 此处可以出现递归调用,直到调用完所有父类的 draw()方法drawBorder();}
private:void drawBorder() { cout << " 边框绘制\n\n"; }
};class Decorator_Horizontal_scroll_bar : public Decorator  // 装饰器:水平滚动条  
{
public:Decorator_Horizontal_scroll_bar(Control* p) : Decorator(p) {}virtual void draw() override{Decorator::draw();draw_Horizontal_scroll_bar();}
private:void draw_Horizontal_scroll_bar() { cout << " 水平滚动条绘制\n\n"; }
};int main()
{Control_List ctrlList;Decorator_border decoBorder(&ctrlList);Decorator_Horizontal_scroll_bar decoBorderHSB(&decoBorder);decoBorderHSB.draw();return 0;
}

以下给出测试结果:

在这里插入图片描述

这里再给出装饰者模式的另一范例(上一例是电脑控件绘图),加佐料的饮料售卖:饮料最初售价 10 元,加了糖再加 2 元, 加了牛奶 再加 2 元。以下是代码,可见与电脑绘图出奇的像 :

class Drink                // 饮料的基类
{
public:virtual ~ Drink() {}virtual int getPrice() = 0;
};class Drink_Fruit : public Drink   // 水果饮料,可以往里再加糖、牛奶
{
public:virtual int getPrice() override { return 10; }  // 啥也不加的水果饮料,价格是 10 元
};class Decorator : public Drink
{
private:Drink* ptrDrink;
public:virtual ~Decorator() {}Decorator(Drink* p) : ptrDrink(p) {}virtual int getPrice() override { return ptrDrink->getPrice() ; }
};class Decorator_Sugar : public Decorator  // 饮料里再加糖,加 2 元
{
public:Decorator_Sugar(Drink* p) : Decorator(p) {}virtual int getPrice() override { return Decorator:: getPrice() + 2 ; }
};class Decorator_Milk : public Decorator   // 饮料里再加牛奶,加 3 元
{
public:Decorator_Milk(Drink* p) : Decorator(p) {}virtual int getPrice() override { return Decorator::getPrice() + 3; }
};int main()
{Drink_Fruit drinkFruit;Decorator_Sugar decoSugar(&drinkFruit);Decorator_Milk  decoMilk(&decoSugar);cout << " 水果饮料,加糖,加牛奶后的价格: " << decoMilk.getPrice() << "\n\n";return 0;
}

测试结果如下:

在这里插入图片描述

谢谢

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

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

相关文章

如何从iPhone恢复错误删除的照片

嘿&#xff0c;iPhone 用户&#xff01;作为一名苹果专业人士&#xff0c;我见过相当多的“哎呀&#xff0c;我删除了它&#xff01;”的时刻。今天&#xff0c;我在这里指导您完成从iPhone中恢复那些珍贵的&#xff0c;错误删除的照片的迷宫。坐下来&#xff0c;拿起你的设备&…

分压电路 ADC计算电压 【老板再也不能开除我了 】

经典分压电路 一个电压过来 adc这里的电压等于&#xff1a; 如是12位adc 那么他最大值就是4095 如参考电压是5v 则&#xff1a;5v/4095 实际电压V*(R2/(R1R2)&#xff09;/adc值 转化&#xff1a;实际电压V 5v*(adc值/4095)/(R2/(R1R2)) &#xff1a;老板再也不能 因为不会…

PointCloudLib-滤波模块(Filtering)-直通滤波

使用直通过滤器过滤点云 在本教程中,我们将学习如何沿着 指定维度 – 即,切断位于 或 在给定用户范围之外。 代码 首先,创建一个文件,比方说,在你最喜欢的 编辑器,并将以下内容放入其中:passthrough.cpp #include <iostream> #include <pcl/point_types.h&g…

推荐系统-FM模型

参考&#xff1a;推荐系统&#xff08;三&#xff09;Factorization Machines&#xff08;FM&#xff09;_svmmf-CSDN博客 一句话概括下FM&#xff1a;隐式向量特征交叉----类似embedding的思想 LR 如果利用LR做特征的二阶交叉&#xff0c;有&#xff1a; 但这个公式存在显著…

Open3D 点云的ISS关键点提取

目录 一、概述 1.1原理 1.2应用场景 1.3算法实现步骤 二、代码实现 2.1 完整代码 2.2关键函数 2.3关键点可视化 三、实现效果 3.1原始点云 3.2提取后点云 一、概述 1.1原理 ISS&#xff08;Intrinsic Shape Signatures&#xff09;关键点提取是一种常用于三维点云的…

【LLM-多模态】高效多模态大型语言模型综述

一、结论写在前面 模型规模的庞大及训练和推理成本的高昂&#xff0c;限制了MLLMs在学术界和工业界的广泛应用。因此&#xff0c;研究高效轻量级的MLLMs具有巨大潜力&#xff0c;特别是在边缘计算场景中。 论文深入探讨了高效MLLM文献的领域&#xff0c;提供了一个全面的视角…

Win10可用的VC6.0绿色版及辅助插件assist_X

VC6.0&#xff0c;作为微软的经典开发工具&#xff0c;承载着无数开发者的青春与回忆。它曾是Windows平台上软件开发的重要基石&#xff0c;为开发者们提供了稳定且强大的编程环境&#xff0c;尤其是其MFC&#xff08;Microsoft Foundation Classes&#xff09;库&#xff0c;为…

SSM宠物领养系统-计算机毕业设计源码08465

目 录 摘要 1 绪论 1.1课题背景及意义 1.2研究现状 1.3ssm框架介绍 1.3论文结构与章节安排 2 宠物领养系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 …

uni-push(2.0)常见问题,Android平台

将常用的网址一定要收藏在标签栏中&#xff0c;方便后期找&#xff0c;不然后期会很生气。 草料二维码&#xff0c;这个在线工具可以将打包生成的apk文件生成二维码&#xff0c;供测试人员测试。生成的apk只有五次下载机会&#xff0c;可点击链接后的一键上传&#xff0c;这样…

数据资产管理的艺术之道:深入探索如何在数据价值的最大化、个人隐私的严密保护以及企业持续发展的战略需求之间找到微妙的平衡

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业最宝贵的资产之一。从市场营销到产品研发&#xff0c;从客户服务到运营管理&#xff0c;数据无处不在&#xff0c;为企业提供了前所未有的洞察力和竞争力。然而&#xff0c;随着数据量的激增和数据类型的多样化&#xff0…

【Linux网络(一)初识计算机网络】

一、网络发展 1.发展背景 2.发展类型 二、网络协议 1.认识协议 2.协议分层 3.OSI七层模型 4.TCP/IP协议 三、网络传输 1.协议报头 2.局域网内的两台主机通信 3.跨网络的两台主机通信 四、网络地址 1.IP地址 2.MAC地址 一、网络发展 1.发展背景 计算机网络的发展…

七天速通javaSE:第三天 程序控制结构:顺序、选择、循环

文章目录 前言一、Scanner类1. hasNext()和hasNextLine()2.next()和nextLine()3. Scanner的其他用法 二、顺序结构三、选择结构1. if单选择结构2. if-else双选择结构3. if-else if多选择结构4. switch选择结构 四、循环结构1. while循环2.do while循环3. for循环&#xff08;常…

表单(forms)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在app1文件夹下创建一个forms.py文件&#xff0c;添加如下类代码&#xff1a; from django import forms class PersonForm(forms.Form): first_na…

C语言·动态内存管理

1. 为什么要有动态内存管理&#xff1f; 例1&#xff1a; //固定的向内存申请4个字节 int a 10;//申请连续的一块空间 int arr[10]; 这些数据一旦声明定义之后就会在内存中有一块空间&#xff0c;这些空间都是固定的&#xff0c;为了让内存使用更加灵活&#xff0c;这时我们…

【复旦邱锡鹏教授《神经网络与深度学习公开课》笔记】卷积

卷积经常用在信号处理中&#xff0c;用于计算信号的延迟累积。假设一个信号发射器每个时刻 t t t产生一个信号 x t x_t xt​&#xff0c;其信息的衰减率为 w k w_k wk​&#xff0c;即在 k − 1 k-1 k−1个时间步长后&#xff0c;信息为原来的 w k w_k wk​倍&#xff0c;时刻 …

SpringBoot开启事务日志

一般框架开启日志的方式&#xff1a; 开启某个包下的日志就写该包路径&#xff0c;开启某个类下的日志就写该类路径。

【数据结构】栈的定义与实现(附完整运行代码)

目录 一、栈的定义 二、顺序栈 链栈比较 三、栈的实现&#xff08;顺序栈&#xff09; 3.1 ❥ 定义栈结构 3.2 ❥ 初始化 3.3 ❥ 销毁 3.4 ❥ 插入&#xff08;入栈&#xff09; 3.5 ❥ 删除 &#xff08;出栈&#xff09; 3.6 ❥ 获取栈顶元素 3.7 ❥ 判空 3.8 ❥…

【Android】创建一个可以在屏幕上拖动的悬浮窗

项目需求 在界面上创建一个悬浮窗&#xff0c;可以自由的移动这个悬浮窗 需求解决 1.添加权限 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW"/>2.请求权限 从 Android 6.0 (API 23) 开始&#xff0c;应用需要动态请求显示悬浮窗…

F5《企业DNS建设白皮书》中的DNS解析服务器最佳实践

在这个数字化转型加速的时代&#xff0c;DNS&#xff08;域名系统&#xff09;的重要性不言而喻。每一次重大事件都凸显了DNS的可靠性和安全性问题。对企业而言&#xff0c;它不仅关系到业务连续性&#xff0c;更是提供永续数字服务的关键。本文根据F5公司发布的《企业DNS建设白…

中国4个民族群体的全基因组DNA甲基化变异图谱首次发布

2023年4月&#xff0c;由西北工业大学联合复旦大学等院校在Science China Life Sciences上发表题为“Genome-wide DNA methylation landscape of four Chinese populations and epigenetic variation linked to Tibetan high altitude adaptation”的文章&#xff0c;该研究通过…