C++继承和组合——带你读懂接口和mixin,实现多功能自由组合

摘要: 本文详细介绍了C++继承的三种方式和相关重要概念,整理了众多继承与组合中的注意问题。在C++继承存在不安全的默认实现,非虚函数的覆盖,多重继承的函数名冲突、菱形继承等众多问题下,如何实现多个功能的自由组合?阿里云高级开发工程师采用mixin,为大家提供了更好扩展性和更高代码复用度的解决方案

摘要:本文详细介绍了C++继承的三种方式和相关重要概念,整理了众多继承与组合中的注意问题。在C++继承存在不安全的默认实现,非虚函数的覆盖,多重继承的函数名冲突、菱形继承等众多问题下,如何实现多个功能的自由组合?阿里云高级开发工程师采用mixin,为大家提供了更好扩展性和更高代码复用度的解决方案。

数十款阿里云产品限时折扣中,赶紧点击这里,领劵开始云上实践吧!

本次直播视频精彩回顾,戳这里! 

演讲嘉宾简介:
付哲(花名:行简),阿里云高级开发工程师,哈尔滨工业大学微电子学硕士,主攻方向为分布式存储与高性能服务器编程,目前就职于阿里云表格存储团队,负责后端开发。

以下内容根据演讲嘉宾视频分享以及PPT整理而成。

本文将围绕一下几个方面进行介绍:
1. C++继承方式
2. 继承相关重要概念及注意问题
3. 问题及解决:如何组合正交的多个功能

一. C++继承方式
C++有三种继承方式:public/protected/private,这三种继承方式中,派生类都会继承基类的public和protected成员,但无法直接访问基类的private成员,只能通过继承后的方法来访问。如图所示一个简单的示例:

在本例中,Base为基类,包含public/protected/private三种成员,其中public和protected成员可以被派生类继承,而mName不可以被派生类直接访问,只可以通过继承后的函数F(),G(),H(),I()来访问。

1. Public继承
采用public继承方式时,基类的成员在派生类中的访问级别与基类中一致,即public成员仍是public级别,protected成员仍是protected级别。如对上例中Base进行public继承,得到下派生类:

其中F()为纯虚函数,派生类只继承到函数的接口,需要再进行具体实现;G()为虚函数,派生类同时继承了接口和实现;H()为public方法,有实现但不为虚函数,无法在调用指针时触发多态,该派生类继承了接口和强制的实现,这是不能改写的;I()是protected方法,它不是基类的接口,因此派生类只继承了它的实现。此时,该派生类可以作为一个基类对象使用,例如上图中创建派生类对象用于两个函数中,此时派生类引用/指针可转换为基类引用/指针。

2. Protected继承
protected继承与public继承的不同在于,基类的成员在派生类中的访问级别的改变。public和protected成员都成为protected级别。此时派生类接口不包含基类的接口,因此protected继承不是is-a的关系。继承后成员如下图所示:


3. Private继承
private继承中,基类的public和protected成员都成为private成员。和protected继承类似,派生类接口不包含基类的接口,因此private继承也不是is-a的关系。同时派生类引用/指针不可转换为基类引用/指针。此外,由于此时派生类成员都为private,那么后续派生类型再也无法继承该类型。对上例中Base进行private继承,如下图所示:

那么综上所述,C++的继承方式中:public继承包括基类的接口与实现;protected继承只包括基类的实现,且可继续传递;private继承只包括基类的实现,且不可继承传递。这里值得注意的是,派生类无法继承基类private成员,这是指派生类无法直接访问,即基类private成员对派生类对象不可见,但在内存布局中是包含这些private成员的,且派生类的构造、析构、复制也会受到这些private成员影响。例如假设基类中有引用private成员,这不仅导致基类方法无法进行复制和移动,也同样会导致派生类的无法复制和移动。

二. 相关重要概念
1. 纯虚函数与抽象类
纯虚函数是声明为等于0的虚函数,具体如下图所示:

此处0填充在虚表中,这会导致纯虚函数的虚表为0项,即无法创建虚表,无法实例化。包含纯虚函数的类称为抽象类,此处Base即为一个抽象类。但这里需要注意的是,纯虚函数不等于无定义的虚函数。如果这里将图中的等于0去掉,即F() = 0改为F(),那么Base类是无法派生的,派生类会报错F()无法使用。

2. 接口继承与实现继承
接口是类与外界的通信协议,是抽象的;实现是类对协议的反应,是具体的。当称派生类继承了基类的某接口时,表示派生类对外的协议中也包含了基类对外的协议,调用该接口时,派生类对象就会被当做基类对象使用。当称派生类继承了基类的某实现时,指派生类可以调用基类的某种行为。与Java和C#不同的是,无论是继承接口还是实现,C++中只有一种继承语法,并且如上所述,public继承包括基类的接口与实现,protected和private继承只包括基类的实现,不包含接口。例如下图中:

当派生类继承基类public方法时,draw()方法为纯虚函数,只能继承到接口,即派生类必须改写该函数,否则不能实例化对象;error()方法为虚函数,继承到接口与默认实现,即若派生类改写了该函数,那么该函数就失效了,若派生类未改写,则可以直接使用该函数;id()方法为非虚函数,继承到接口与强制实现,即派生类无法改写该方法。

3. 安全的默认实现
大家可能觉得派生类需要给每个纯虚函数进行实现,太过繁琐,虚函数效果更佳。若该纯虚函数较为通用,可能在派生类中需要重写多遍,而虚函数提供了一个默认实现,只需在需要时改写即可。但请注意,这其实是非常危险的。因为在编写基类时是不知道未来将会产生哪些派生类,默认实现不一定适用所有派生类。例如下例中:

ModelA和ModelB都可以使用基类的默认实现,但后续加入了不能使用基类的默认实现的ModelC,此时理应为ModelC改写该实现但被编程人员遗忘了。编译时由于存在基类的默认实现,因此不会报错。运行初期可能不会出现问题,但会为后续埋下非常危险的隐患。因此严格的代码规范中禁止虚函数提供默认实现,即必须使用纯虚函数。但虚函数可以避免代码的重复,因此仍存在一定的价值。实际运用中,存在很多派生类需要使用默认实现,那么如何强制要求派生类显式地使用每个接口,又可以为派生类准备一个可调用的默认实现呢?一种方法就是为纯虚函数提供定义。这种定义不会存入虚表,因此基类本身仍然是抽象类,并且派生类仍然需要提供一个显式实现。但更简便的方法是在派生类中调用基类的实现,注意此处不能使用虚函数,而是直接使用函数名调用。如下图示例所示:

如此,需要使用默认实现时只需简单调用该函数;而不需要使用默认实现时,若程序员忘记编写具体实现,编译时便会报错,强制要求提供函数实现。因此,便可以避免上述默认实现的隐患。

4. 纯接口继承与接口类
纯接口继承是指基类只提供接口,不提供定义,即严格代码规范下,基类的所有函数都是纯虚函数,不提供具体实现,派生类需要对所有方法进行自定义,这样的类型称为纯接口类。纯接口继承完全分离了接口与实现,依赖更少,如下例所示:

这样的接口类有以下三个特点:一,没有非静态成员变量;二,所有成员都是public成员;三,所有成员都是纯虚函数,析构函数除外,因此在上例Interface类中存在一个有定义的虚的析构函数。纯接口继承的优点是最小化调用处的依赖,且接口与实现完全分离,这样在只有实现发生变化时,调用处不会受到任何影响。而它的缺点是不利于代码复用,如果多个派生类都要实现相差不多的方法F(),就需要重复编写多遍F()的代码。

5. 确保接口继承是“is-a”关系
在实行接口继承时,需要确保接口继承是“is-a”关系。当派生类以public方式继承一个基类时,它也继承了这个基类的所有接口,那么所有使用基类接口处都可以使用派生类。从这个角度说,派生类对象是一个(“is-a”)基类对象。这也是基类接口对派生类的约束,派生类需要严格保证其所有行为都符合基类接口的要求。但有时派生类并没有达到这一要求,如下经典示例所示:

本例中,基类Bird包含接口fly,正如大家理解,鸟都会飞。Penguin继承自Bird,如果采用默认实现那么Penguin也要继承接口fly。但大家知道企鹅不会飞,也就意味着它不能有fly接口。如果这里给Penguin一个空的fly方法,虽然可实行,但这是不合常理的,必须要向使用者显示Penguin是不含有fly行为的。如果此处不给出具体实现的话,只有在运行时才会抛出异常,这种意外的异常也是不友好的。这个问题其实源于对基类接口的设计。当已知不是所有鸟都会飞之后,那么便不应该给Bird类一个fly接口,基类的这种接口是一种不合理的强加的约束。一种解决方法是中间再加一个层次:Bird类本身是没有接口的,而Bird的派生类FlyingBird才会提供fly接口,那么Penguin便继承Bird类,而不是继承FlyingBird类。如此若调用Penguin类的fly接口,编译时就会报错,便可以防止上述问题的发生。另一个示例为矩形的实现,如下所示:

长方形类中有一提前假设,即它的长和宽是独立的,改变其中一个值,另一个值不会随之改变。makeBigger就体现了这种假设,这也是对所有长方形的派生类的要求。但正方形却不满足这个要求,它的长和宽必须是相等的。因此正方形根本不应该是长方形的派生类,这种继承是错误的。由此可见,C++中的继承比现实中的继承更加严格,需要编程人员谨慎的选择基类与派生类,任何适用于基类的性质都需要适用于派生类。存在任何不满足“is a”关系的继承都是不合理的。

6. 不要覆盖基类的非虚函数
当派生类public继承一个有非虚函数的基类时,派生类也会继承这个非虚函数,并且是继承了强制实现。然而与虚函数不同的是,派生类没办法改写这个函数,相反,如果自定义编写一个同名函数,基类的版本就被“覆盖了”,如下例所示:

派生类和基类中都有函数F(),但此处不是改写而是覆盖,基类接口被覆盖会导致调用产生的行为不一致。直接通过派生类对象调用F()与通过基类指针调用F(),会产生不一样的行为!这种不一致就表明派生类与基类不再是is a的关系。因此,不要覆盖基类的非虚函数。

7. 实现继承与组合
当派生类以protected或private继承一个基类时,派生类没有继承到基类的接口,而是继承到了基类的实现。这种方式被称为实现继承。实现继承意味着派生类与基类不是is-a的关系,而只是需要复用其实现或功能。例如,若有一个类Password,它需要使用std::string功能,那么一种解决方法就是让它继承自std::string,如图所示:

此时Password类便可以直接调用string方法。但string类本身并没有设计为可以成为一个基类,可能存在其析构函数不是虚函数,那么使用基类指针指向析构函数时,会忽略派生类对象中的内容。但这里还有另一种选择,那就是将std::string变成Password的一个成员,而不是Password的基类,这样仍能使用std::string的各种功能,且不需要增加一种继承关系。这种方法被称为“组合”,它是比继承更灵活的复用方法。一般在可以用组合达到目的时,要尽量避免使用实现继承。然而,在某些场景下,实现继承有它独特的用途。一是在改写基类的某些功能时,如下例所示:

当Widget只需要复用Timer的其他功能,但不需要Timer的onTick()时,就可以使用private继承Timer,然后改写onTick()函数,这是对象组合无法轻易完成的。当然该场景下,结合内部类,组合也可以达到类似效果。用内部类private继承Timer,与Widget构成组合关系,如此来避免Widget直接继承Timer。
第二种场景是当基类是空类型时,继承可以应用到空基类优化,在派生类中不占空间,而对象组合则没有这种优化,空类型成员至少要占用一字节的空间,一般会在八字节及以上。该场景最经典的例子是boost::noncopyable,无论是private继承,还是将其作为成员变量,都可以令自定义类型无法复制,但private继承时,因为该基类是空类型,因此在派生类中不占空间。实现继承的该特性在标准类型库中被广泛使用。

8. 多重继承的问题
C++允许一个派生类继承自多个基类,但逐渐大家意识到这种自由会导致一些棘手的问题,因此Java等语言取消了这种特性,而是派生类只允许有一个基类。多重继承会导致以下两个问题。一是不同基类间的名字冲突或者歧义,如下例所示:

此处有A和B两基类,C同时继承A和B。虽然A类中的Func()是public函数,B中的func()是private函数,但调用C类的func()函数时,它理应调用A的func(),但C++的名字查找规则是优先于访问级别检查的,因此先查找名字,进行重载决议,再检查访问级别,而在重载决议时编译器检查到了两个相同优先级的func(),这就产生了冲突。解决这个问题就需要显式调用某个基类的版本,指定调用函数的namespace:

第二个问题是菱形继承问题,这比上述问题更加棘手。当语言允许多继承时,一个基类可能会多次出现在同一个派生类的基类树中,如下例所示:

InputFile和OutputFile同时继承于File类,而下一层IOFile类同时继承InputFile和OutputFile,即继承了两次File,这就是菱形继承。当出现菱形继承时,意味着派生类对象中有多个相同类型的基类子对象,此时调用该基类方法时会产生如何选择子对象的混乱。并且有些属性对派生类是唯一的,比如File属性,在IOFile中只应有一份。为了解决这个问题,C++增加了虚继承,虚继承的基类在派生类中只会有一份。但虚继承被认为是比多重继承更糟糕的特性,它比虚函数的开销更大,且反直觉地要求最终派生类型的构造函数来构造整个继承链条中所有虚继承的基类。因此,为了避免菱形继承,一些编程规范规定:不能使用虚继承;尽量不要使用多重继承;如果要用多重继承,尽量模仿Java语言,至多只能有一个基类有实现,其它基类都是接口类。

三. 问题及解决:如何组合正交的多个功能
假设有若干个彼此独立,或说正交的功能,如何将它们组合起来?例如有一个TaskManager类,负责管理所有拥有ITask接口的对象,如下所示:

现在需要为ITask类型增加两个功能:一是timing功能,即在ITask对象执行Execute方法前后计时;二是logging功能,即在ITask对象对待Execute方法前后打印日志。那这该如何解决呢?

1. 继承
第一种方式是通过继承复用功能。具体如下所示:

从ITask类派生出一个ILoggingTask类,它增加OnExecute()接口,其派生类只要实现这个接口,在调用ITask::Execute时就能打印日志了。同样的方法,这里也通过增加ITimingTask类实现timing的功能:

然而当需要同时复用timing和logging该如何解决呢?假设使用上述方法,那么ITimingTask的Execute()与ILoggingTask的Execute()是冲突的,无法同时复用两个功能。这就体现了通过继承来复用代码的缺陷,对于单个功能,可以将需要复用的实现代码放在基类中,但如果需要同时复用多个功能,通过继承复用功能就无法解决了。另外,本例中因为增加了一层虚函数,而且还是在虚函数中调用另一个虚函数,这就导致编译器无法inline代码,从而增加运行期的开销。

2. 组合
第二种方式是通过组合复用功能。具体如下所示:

这里LoggingTask不再作为基类存在,而是作为代理,把对LoggingTask的请求转发给它持有的task成员,由task来解决请求。同样地,这里也增加一个TimingTask类:

接下来就可以通过链式传递来组合这两个功能。

通过组合来复用功能仍然也存在一些问题。一是这种方法依然有一些运行期的开销,比如需要在堆上分配每个对象,多次调用虚函数。但它解决了组合多个功能的问题,不同功能间也耦合较低。二是LonggingTask需要实现一些不用的接口。像LoggingTask这样纯粹的功能,本是不需要实现GetName这样的接口,但它继承自ITask,就需要实现ITask所有的接口。假如ITask还有其它接口,LoggingTask也都需要实现,这就增加了代码的复杂度,使得该模块特别臃肿。那么这该如何解决呢?

3. 重返继承
这次仍然尝试用继承来解决该问题,但与上述第一种继承方法相比,做出一些变化。前面的方法中增加了两个基类,且把需要复用的部分放在基类中。而这里把需要复用的部分放在派生类中:

这里将MyTask作为基类,TimingTask中继承MyTask来执行计时的操作。而LoggingTask继承TimingTask,如此LoggingTask便同时具有计时和打印两个功能。但这种方法仍然有很多缺陷:一是不同功能之间因为继承完全耦合在一起,功能之间无法分割;二是这两个功能绑定在MyTask类中,导致这两个功能完全无法被其它类型复用。虽然有这么多致命缺陷,但这种方法仍然有独特的优势:首先,不需要堆分配;其次,没有多余的虚函数定义及其调用;最后,编译器有机会做更多内联优化。那么,该如何解决这个方法的缺点呢?由代码分析可知,上例中的两个缺点都是因为基类是固定的,无法变化,如果能用模板将基类作为参数传递,上述缺点便解决了。

4. Mixin
最后一种方法是通过mixin复用功能。mixin本身是面向对象领域的一个非常宽泛的概念,它是有一系列被称为mixin的类型,这些类型分别实现一个单独的功能,且这些功能本身是正交的。当需要使用这些功能时,就可以将不同的mixin组合在一起,像搭积木一样,完成功能复用。一个更清晰的解释是这样的:一个mixin就是类里的一小块,可以用来与其它类或mixin做组合;一个独立的类与一个mixin的区别在于,一个mixin只建模小的功能点(如timing或printing),并不是用来独立使用,而是给其它需要这个功能的类做组合。
在C++中最常用的实现mixin的方式叫“参数化模板”。这里可以将TimingTask和LoggingTask的基类都换成模板参数:

此时便可以解决前述所有问题,TimingTask和LoggingTask实现完全不耦合,所有代码独立,且所有含有Execute()方法的类型都可以组合这两个功能。组合过程如下所示:

首先新建MyTask对象,将该对象传递进入TimingTask类中,生成对象t1,然后可以将t1传递进LoggingTask类中生成对象t2。t2便同时具备Timing和Logging功能。
C++可以通过继承方法来支持mixin,而不像其他语言,如Ruby,显式的支持mixin。如此使用mixin便能够实现自由组合多个功能,并且囊括了之前方法的所有优点,有更好的扩展性和更高的代码复用度。
当然这个类并不是最终希望得到的,因为它没有实现ITask接口。因此仍然可以增加一个新的mixin,来将任意含有Execute和GetName方法的类型适配为ITask的派生类:


本文由云栖志愿小组郭雪整理,编辑百见

原文链接

干货好文,请关注扫描以下二维码:



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

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

相关文章

如何在阿里云•对象存储OSS托管用户域名的https证书

摘要: OSS服务支持将用户域名绑定到OSS域名,并为此用户域名提供HTTPS证书托管服务。以满足用户使用自己的域名也能支持HTTPS安全加密的访问方式传输数据。面向人群您已经拥有了自己的域名。您已将或准备将自己的域名绑定到OSS域名上,并且使用…

win10系统VMware Workstation与Device/Credential Guard不兼容怎么办

解决方法: 打开本电脑-》管理-》服务和应用程序-》服务下找到如下图的HV 主机服务,双击选择禁用。 或者 转到“ 控制面板” >“ 卸载程序” >“ 打开或关闭Windows功能”以关闭Hyper-V。 步骤二:通过命令关闭Hyper-V(控制…

数据大爆炸边缘期 让存储告别旧时代

戳蓝字“CSDN云计算”关注我们哦!好莱坞一部高智商大数据电影《永无止境》,讲述一位落魄的作家库珀,服用了一种可以迅速提升智力的神奇蓝色药物。他将这种高智商用于炒股,能在短时间掌握无数公司资料和背景,也就是将世…

AliOS Things图形界面开发指南

简介物联网设备开发过程中,嵌入式GUI(用户图形界面)的开发是一个重要的组成部分。许多智能设备如智能家电、智能手表、智能仪表上都会涉及到GUI开发。AliOS Things集成开源图形库littlevGL,可以在linux上进行图形界面开发。开发完…

微服务的好处与弊端_《微服务架构设计模式》-学习总结07

本篇主要总结第七章:在微服务架构中实现查询在微服务架构中查询数据的挑战何时以及如何使用API组合模式实现查询 何时以及如何使用CQRS模式实现查询 微服务架构中,查询通常需要检索分散在多个服务所拥有的数据库中的数据,跨服务数据查询的两种…

ECS主动运维2.0,体验升级,事半功倍

摘要: 阿里云致力于提供更好用的运维体验,让您使用ECS的过程更透明、高效,并实现更加标准化、自动化的运维方式。基于主动运维2.0,您使用ECS云服务器的体验更加流畅,而且利用系统事件,不再依赖于工单联系客…

mysql bench如何下载_MySQLWorkbench下载与使用教程详解

一、MySQL Workbench的下载Workbench是MySql图形化的管理工具,可以在Workbench里输入MySql的语句,这可能更适合大多数人的视觉,有些操作更能更简单化首先我们下载workbench然后选择download选择no thanks,just download下载后点击…

为什么说边缘计算的发展比5G更重要?

戳蓝字“CSDN云计算”关注我们哦!由TechSugar编辑部翻译自medium文︱Pavel Konecny本篇文章转自公众号TechSugar(ID:techsugar)边缘计算相对于5G都有哪些优势?犹记2016年,我在汉诺威参加德国汉诺威消费电子、信息及通信…

ICDE:POLARDB定义云原生数据库

摘要: 4月17日(巴黎时间)阿里云POLARDB走出国门,亮相ICDE2018,并同步举办阿里云自有的POLARDB技术专场。在会上,阿里云进行了学术成果展示,从而推动Cloud Native DataBase成为行业标准。4月17日…

PLSQL连接ORACLE

文章目录① 安装oracle服务端②安装plsql③配置监听④配置2个⑤重启plsql① 安装oracle服务端 ②安装plsql ③配置监听 ④配置2个 【打开客户端】-【取消】-【工具】-【首选项】-【连接】 配置截图2个配置 【Tools】-【Preferences】-【Connection】 根据自己的oracle安装路…

新功能:阿里云负载均衡SLB支持HTTP访问强制跳转HTTPS

摘要: 很高兴的告诉大家,阿里云负载均衡SLB已经在澳大利亚(悉尼)、日本(东京)、阿联酋(迪拜)、美国 (弗吉尼亚)、美国(硅谷)、马来西亚…

算法一看就懂之「 堆栈 」

戳蓝字“CSDN云计算”关注我们哦!今天咱们再来继续看看「 堆栈 」吧,我写技术文章很少 show code,所以经常有人吐槽。好吧,这个算法系列的文章我打算每一篇的结尾处都找一道算法题写出代码示例,这总可以了吧。一、「 堆…

Centos/Red Hat7.9 源码和在线yum 安装 vsftpd

文章目录一、版本简述1. 环境介绍2. 常用命令二、源码下载2.1. 官网链接2.2. 下载方式2.3. 检查2.4. 源码安装2.5. 异常处理2.6. 检查是否安装成功一、版本简述 1. 环境介绍 软件系统版本Red Hat Enterprise Linux Server7.9 (Maipo)CentOS Linux release 7.9(Core)jdk1.8.0_…

阿里云黄海宇:窄带高清2.0——让直播更惊艳的魔术

摘要: 2018年4月11-12日,2018亚太CDN峰会在北京隆重召开,大会由亚太CDN领袖论坛、电视云论坛、短视频论坛、视频云论坛、新技术论坛、运营商论坛、国际云论坛等7大部分组成。在视频云论坛上,阿里云视频云高级算法专家黄海宇作了题…

vsftpd:500 OOPS: vsftpd: refusing to run with writable root inside chroot ()错误的解决方法

原vsftpd服务器的系统从centos6.8升级到centos7.2。vsftpd使用yum方式安装,用户采用系统用户登录。由于系统升级到centos7,yum安装的vsftpd版本改变。因此按centos6的设置,登录时报错。配置文件未修改,主要是修改了ftp的主目录权限…

学Python后到底能干什么?网友:我太难了

感觉全世界营销文都在推Python,但是找不到工作的话,又有哪个机构会站出来给我推荐工作?笔者冷静分析多方数据,想跟大家说:关于超越老牌霸主Java,过去几年间Python一直都被寄予厚望。但是事实是虽然上升趋势…

基于PCDN技术的无延时直播方案

摘要: 2018亚太CDN峰会在北京隆重召开,在4月12日上午的运营商论坛中,阿里云边缘计算团队高级技术专家张士波进行了《基于PCDN技术的无延时直播方案》的主题演讲。本文为演讲内容。当大家谈到直播,一般很惊讶于直播近几年来发展的规…

VSFTPD Centos 7.6 _配置篇

接上一篇:企业内部)Centos7.6 源码安装vsftpd https://gblfy.blog.csdn.net/article/details/103491052 文章目录一、常用命令二、 需求案例三、思路分析3.1. 创建用户3.2. 配置3.3. 限制用户活动范围四、coding实战4.1. 家目录调整4.2. 为test设置密码4…

阿里云弹性计算负责人蒋林泉:亿级场景驱动的技术自研之路

戳蓝字“CSDN云计算”关注我们哦!作者 | 刘丹出品 | CSDN云计算(ID:CSDNcloud)近年来随着云计算如火如荼的发展,上云已经成为当前企业的必经路径。但在国内良莠不齐的云服务市场下,云服务器的选型评估长期困…

阿里云容器Kubernetes监控(一) - 资源监控

摘要: 容器通过集装箱式的编译、打包、部署,大大提高了应用的迭代速度。对于架构师而言,容器带来的是分钟级的部署、秒级的伸缩与恢复、一个量级的迭代速度提升、50%左右的基础成本节省。简介容器通过集装箱式的编译、打包、部署&#xff0c…