10玩rust_C++工程师的Rust迁移之路(5)- 继承与组合 - 下

2020-11-25 更新:

  1. 修正了C++ 20中的concept语法

在上一篇文章 https://zhuanlan.zhihu.com/p/76740667 中,我介绍多态、静态分发和动态分发的概念,以及他们各自在C++和Rust中的实现方式。

在本文中,我会重点讲Rust中的Trait实现的静态分发与C++ 20(准确的说,现在还叫做C++ 2a)中的concepts的区别。

在具体介绍这个区别之前,我想跟大家介绍一个概念,叫做duck typing(鸭子类型)。

鸭子类型

呃……你没有看错,这个鸭子就是你平常理解的那个鸭子,我也没有翻译错……

鸭子类型[1]是鸭子测试的一个应用:

如果它走起来像鸭子,也跟鸭子一样发出嘎嘎的叫声,那么它就是鸭子

听起来似乎非常无厘头,但这个模式实际上被广泛的应用于多种语言。

在C++中的应用

template <typename T>
concept Stream = requires(T a, std::uint8_t* mut_buffer, size_t size, const std::uint8_t* buffer)
{{ a.read(mut_buffer, size) } -> std::convertible_to<size_t>;{ a.write(buffer, size) } -> std::convertible_to<size_t>;
};class Console { ... };
class FileStream { ... };

在Golang中的应用

type Stream interface {Read(uint32) []byteWrite([]byte) uint32
}type Console struct { ... }
type FileStream struct { ... }func (c Console) Read(size uint32) []byte {...
}func (c Console) Write(data []byte) uint32 {...
}

在上面的两个例子中,我们可以注意到,Console和FileStream这两个类型都没有显示的声明自己兼容Stream concept(interface),但在编译阶段,编译器可以根据他们实现的方法来判断他们支持Stream要求的操作,从而实现多态。

这个功能看似非常诱人,省去了显式声明的麻烦,但也带来了问题。

鸭子类型的局限性

程序员的造词能力通常是非常匮乏的(大家每次要给变量命名时的抓耳挠腮可以证明这一点),所以非常容易在方法名上重复,但在两个语境中又可能具有完全不同的语义。

举个例子:

template <typename T>
concept Thread = requires(T a, int signal) {{ a.kill(signal) };
};class DuckFlock {
public:void kill(int amount);
};void nofity_thread(Thread& t) {t.kill(SIGUSR1);
}

原本我以为给鸭群发了一个信号,让它们打印一下状态,结果一不小心就杀掉了10只鸭子[2],真的只能召唤华农兄弟了。

Rust的设计

在Rust中,是不允许这种情况出现的,必须显式的生命类型实现的是哪个trait:

trait Thread {fn kill(&mut self, signal:i32);
}trait Flock {fn kill(&mut self, amount:i32);
}struct DuckFlock {ducks: i32
}impl DuckFlock {pub fn new(amount: i32) -> DuckFlock {DuckFlock{ ducks: amount }}
}impl Thread for DuckFlock {fn kill(&mut self, signal: i32) {if signal == 10 {println!("We have {} ducks", self.ducks);} else {println!("Unknown signal {}", signal);}}
}impl Flock for DuckFlock {fn kill(&mut self, amount: i32) {self.ducks -= amount;println!("{} ducks killed", amount);}
}fn main() {let mut flock = DuckFlock::new(100);{let thread:&mut Thread = &mut flock;thread.kill(10);}{let flock:&mut Flock = &mut flock;flock.kill(10);}{let thread:&mut Thread = &mut flock;thread.kill(10);}
}

同样的,这个例子我也放到Rust Playground,欢迎大家前去玩耍。

Markers

在Rust中,由于实现Trait必须要显式声明,这就衍生出了一种特殊类型的trait,它不包含任何的函数要求:

trait TonyFavorite {}
trait Food {fn name(&self) -> String;
}struct PeikingDuck;impl Food for PeikingDuck {fn name(&self) -> String {"Peiking Duck".to_owned()}
}impl TonyFavorite for PeikingDuck {}struct Liver;impl Food for Liver {fn name(&self) -> String {"Liver".to_owned()}
}fn eat<T: Food + TonyFavorite>(food: T) {println!("Tony only eat his favorite food like {}", food.name());
}fn main() {eat(PeikingDuck);// eat(Liver); // compile error
}

这里例子的Playground在此。

事实上,在Rust中,类似的Marker还有非常多,比如Copy、Sync、Send等等。在后续的文章中,再跟大家逐一解释这些trait的含义与妙用。

在下一节的文章中,我会介绍Rust类型系统和C++类型系统最大的不同之一:Rust结构体不能继承,以及为什么。敬请期待。

延伸阅读

上一篇

黄珏珅:C++工程师的Rust迁移之路(4)- 继承与组合 - 中​zhuanlan.zhihu.com

下一篇

黄珏珅:C++工程师的Rust迁移之路(6)- 继承与组合 - 后​zhuanlan.zhihu.com

参考

  1. ^Duck typing https://en.wikipedia.org/wiki/Duck_typing
  2. ^在Linux下SIGUSR1等于10

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

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

相关文章

带老弟做个实时排行榜

阿巴可懂的实时排行榜设计和实现思路。大家好&#xff0c;我是鱼皮&#xff0c;暑假快到了&#xff0c;我的老弟小阿巴听说我家有很多好康的&#xff0c;就跑来找我玩。结果我摆出了几个以前开发过的小系统&#xff0c;准备在这段时间带着小阿巴多做些作品&#xff0c;学习编程…

c++ memcpy与strcpy的比较

1&#xff1a;区别memcpy可以拷贝任何数据类型的对象&#xff0c;指定拷贝的数据长度。strcpy只能拷贝字符串了&#xff0c;它遇到\0就结束拷贝2&#xff1a;性能static inline char *__kernel_strcpy(char *dest, const char *src){char*xdest dest;asmvolatile("\n&quo…

每日一笑 | 在托运行李时,怎样才能不会因为超重被罚钱?

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

加时间水印_如何在手机照片上添加时间和日期?打开这个设置即可添加,超方便...

经常在朋友圈或者微博刷到一些照片&#xff0c;上面带有拍照时间和地点&#xff0c;甚至是天气&#xff0c;很多人还不知道是怎么操作的吗&#xff0c;今天小编就来告诉大家怎么操作&#xff0c;1分钟包学包会&#xff01;1、照片添加文字、地址、天气打开手机相机&#xff0c;…

少儿编程教育是“揠苗助长”还是要培养未来的程序员?

▲数据汪特别推荐点击上图进入玩酷屋去年有一款名叫CoderMindz的棋类游戏在硅谷名声大噪&#xff0c;它的前身CoderBunnyz发布不到一年时间&#xff0c;销量超过1000余套&#xff0c;销售额以超35000美元&#xff0c;因此大家对新款CoderMindz充满期待。而这款游戏的开发者&…

创建一个列表

/* Note:Your choice is C IDE */#include "stdio.h"#include "malloc.h"struct node{intdata;structnode *next;};typedef struct node NODE;NODE *create_linklist(int n){NODE*p,*q,*head;inti;p(NODE*)malloc(sizeof(NODE));headp;printf("请输入…

日志ILog(文件日志/控制台日志/控件日志/网络日志)

日志组件是NewLife系列组件最早最基础&#xff0c;同时也是流血流泪最多的一个模块&#xff0c;它的底蕴定能感动每一个用户&#xff01;没有日志的应用系统是不完整的。系统遇到啥问题&#xff0c;翻日志看看当时上下文&#xff0c;实在分析不出问题&#xff0c;修改代码再打几…

php crypt mysql password_php使用crypt()函数进行加密

一、代码$str 应用crypt()函数进行单向加密!; //声明字符串变量$strecho 加密前$str的值为&#xff1a;.$str;$crypttostr crypt($str); //对变量$str加密echo 加密后$str的值为&#xff1a;.$crypttostr; //输出加密后的变量?>二、运行结果参数不带salt&#xff0c;每次…

.NET 容器环境下创建应用 dump 文件

.NET 容器环境下创建应用 dump 文件Intro有时候我们的应用会出现一些异常的情况&#xff0c;比如内存飙升&#xff0c;线程死锁等等&#xff0c;通过一些 metrics 我们可能大概的了解内存是增长了&#xff0c;但是具体是哪里增长了&#xff0c;单单看内存的变化很难看出来哪里导…

安装mysql二进制文件_MySQL二进制文件规范安装

演示环境介绍操作系统&#xff1a;CentOS 6.7 (64位)二进制包&#xff1a;MySQL-5.6.30-linux-glibc2.5-x86_64.tar.gzMySQL 下载地址&#xff1a;http://dev.mysql.com/downloads/1、下载MySQL# mkdir /root/mysql# cd /root/mysql# wget http://dev.mysql.com/get/Downloads…

清华体质优良可降5分录取;窃取密钥者奖百万;阿里投入1亿保护方言;腾讯不正当竞争被罚;这就是今天的大新闻...

今天是3月21日农历二月十五今天星期四网络突然变得特别的卡严重影响到我的激情下面是今天的大新闻清华体质优良可再降5分录取&#xff08;中国新闻网&#xff09;据清华大学招生办公室官方微信消息&#xff0c;2019年清华大学将继续在自主招生中开展体质测试。体质测试成绩优良…

[Android]关于IntentService

2019独角兽企业重金招聘Python工程师标准>>> IntentService其实是Service加Handler的组合&#xff0c;Handler存在于专门的HandlerThread上&#xff0c; 区别于UI thread, Service每通过onStart()收到Intent&#xff0c;则转给Handler,通过handleMessage()的方式一个…

Facebook 竟然把服务 27 亿人的 AI 硬件系统开源了?!

全世界只有3.14 % 的人关注了数据与算法之美一直以来&#xff0c;社区对 Facebook 的硬件研究比较关注。在今日的开放计算项目全球峰会上&#xff0c;Facebook 技术策略主管 Vijay Rao 开源了全新的 AI 硬件&#xff1a;面向 AI 训练与推理的硬件系统 Zion 与 Kings Canyon&…

一秒创建高级查询服务

在业务开发中&#xff0c;一个常用的功能就是“高级查询”&#xff0c;就是客户可以根据自己的需要设置查询条件查找数据&#xff0c;类似下图&#xff1a; 通常&#xff0c;我们需要为每个“高级查询”定制Dto类&#xff0c;用于传输条件&#xff0c;并要根据条件组合成查询语…

SQL Server CONVERT() 函数

定义和用法 CONVERT() 函数是把日期转换为新数据类型的通用函数。 CONVERT() 函数可以用不同的格式显示日期/时间数据。 语法 CONVERT(data_type(length),data_to_be_converted,style) data_type(length) 规定目标数据类型&#xff08;带有可选的长度&#xff09;。data_to_be_…

首款产后抑郁药问世;京东推出城市操作系统;阿里将推出全新销售平台;香港政府砸5300亿填海;脸书再爆隐私丑闻;这就是今天的大新闻...

今天是3月22日农历二月十六今天星期五一周就这么过去了周末得好好耍下面是今天的大新闻首款产后抑郁药问世&#xff08;红星新闻&#xff09;据美国CNN新闻3月19日报道&#xff0c;当地时间本周二&#xff08;19日&#xff09;&#xff0c;美国食品和药物管理局&#xff08;FDA…

navicat如何连接腾讯mysql_使用Navicat连接腾讯云Mysql数据库

1、安装# 安装mysql服务sudo apt-get install mysql-server# 安装客户端sudo apt install mysql-client# 安装依赖sudo apt install libmysqlclient-dev# 检查状态sudo netstat -tap | grep mysql2、设置密码root> mysqlmysql> update mysql.user set authentication_str…

WPF实现环(圆)形进度条

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织“ 前言&#xff0c;接着上一篇圆形菜单。”欢迎转发、分享、点赞、在看&#xff0c;谢谢~。 01—效果预览效果预览&#xff08;更多效果请下载源码体验&#xff09;&#xff1a;02—代码如下一、…

JQuery上传插件Uploadify使用详解

Uploadify是JQuery的一个上传插件&#xff0c;实现的效果非常不错&#xff0c;带进度显示。不过官方提供的实例时php版本的&#xff0c;本文将详细介绍Uploadify在Aspnet中的使用&#xff0c;您也可以点击下面的链接进行演示或下载。官方下载官方文档官方演示首先按下面的步骤来…

每日一笑 | 不忘初心,最爱扫雷~

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图源网络&#xff0c;侵权删&#xff09;