• C++的发展与抽象


    在此之前先说一些概念:

    计算机最重要的两个元件:CPU(控制器、运算器)、存储设备(寄存器、缓存、内存、硬盘)。

    算法需要实现,所以有了CPU,CPU需要运行算法,所以有了指令集、程序段,高级语言编写函数代替编写程序段。

    算法运行需要数据支撑,且算法本身需要存储起来,所以有了 存储设备,存储设备可以永久存储数据,程序编写中变量就是数据。永久存储速度太慢,所以有了缓存设备和存储器体系。

    冯诺依曼最杰出的思想就是:把算法记录成指令,当做数据存放,于是算法和数据完美结合,产生了冯诺依曼体系计算机。这和人类似,仔细一想,人的大脑也有计算和存储功能。

    杂谈:

    两年前看了《黑客与画家》这本书,当时觉得非常有趣,书的后半部分 作者大力鼓吹Lisp语言,说了lisp语言是未来的编程语言,极度抽象,能非常省力的做到其他语言很难做到或根本做不到的事情。

    其中举了一个很贴切的例子,他写了一段简短的lisp代码,参数是一个函数,返回值也是一个函数。也就是能够将函数当做数据进行处理。相当于把代码当做数据进行处理。

    这个能力是非常有吸引力的,在C++中,代码就是.text,数据就是.data,区分的非常明显。而在lisp中,代码和数据没有明显的区分。

    有人称lisp为面向语言的语言、函数式编程的鼻祖、变态的语言、非正常人使用的语言......

    lisp的确吸引了我,作者说最值钱的是人力,所以把事情尽可能多的交给程序去做,lisp正是这样一门语言,它能将算法当做数据来用,所以它能在人工智能领域施展拳脚。

    当我尝试去学lisp时,发现它的代码全是括号,表达式(+ 3 4)的结果是7,而正常的语言都是3+4。所以读lisp代码感觉有些困难。最后我没有使用lisp。但是我还是愿意称它为函数式编程的鼻祖。

    近年来,函数式编程被众多语言接受,python就支持函数式。今天我要说的是我经常用的C++所支持的函数式。

    我仔细想,为啥lisp如此灵活的把函数和数据结合起来。最后想出来,lisp和python都是动态语言,在运行时才生成指令,所以运行的时候可以动态生成代码。而C++是静态语言,在编译期就把指令定死了。所以C++如果支持函数式编程,那一定是在编译器决定下来了。

    果然,从C语言的函数指针,到C++的函数对象,再到C++11的lambda、functional、bind。都是在编译器完成的函数式,及通过元编程(宏定义、模板)实现。

    函数装饰器:

    在《黑客与画家》中作者贴出来的lisp代码,正是一个函数装饰器,及接受一个函数,对这个函数进行修改,再返回一个新的函数。这个功能就称为函数装饰器。当时他认为C++是完全实现不了这个功能的,我尝试了很多次,的确实现不出来,但是最近在ceph代码中发现了函数装饰器的影子,虽然没有lisp的简洁,但是功能还是实现出来了:下面我就直接贴代码吧。

    #include <utility>
    class Decorator
    {
    public:
    	template <typename Callback, typename...Args>
    	decltype(auto) ret(Callback&& cb, Args&&... args)
    	{
    		//log
    		printf("begin
    ");
    		printf("to do some things
    ");
    		auto ret = std::forward<Callback>(cb)(std::forward<Args>(args)...);
    		//log
    		printf("end
    ");
    		printf("to do some things
    ");
    		return ret;
    	}
    	template <typename Callback, typename...Args>
    	void voi(Callback&& cb, Args&&... args)
    	{
    		//log
    		printf("begin
    ");
    		printf("to do some things
    ");
    		std::forward<Callback>(cb)(std::forward<Args>(args)...);
    		//log
    		printf("end
    ");
    		printf("to do some things
    ");
    	}
    };
    
    int add(int a, int b) {  return a + b; }
    void sub(int a, int b) {}
    int main()
    {
    	Decorator dec;
    	dec.ret(add, 1, 3);
    	dec.voi(sub, 1, 3);
    	system("pause");
    	return 0;
    }
    

      

    其中,ret函数模板可以封装 有返回值的函数,voi函数模板可以封装 无返回值的函数。可以自行体会, 然后根据自己的需求进行修改。

  • 相关阅读:
    mysql在第一次查询的时候很慢,第二次查询就比较快的原因?
    mysql的递归(使用函数)
    什么样的男人才是女人眼中最帅的男人
    面试题总结
    java的重载总结
    arduino读取GPIO数据
    electron+react项目改为typescript
    百度AI训练营笔记
    python读取文件出现ufeff问题
    大端小端
  • 原文地址:https://www.cnblogs.com/xjjsk/p/11692718.html
Copyright © 2020-2023  润新知