http://my.oschina.net/fzyz999/blog/138491

关于本文

  本文是笔者在阅读《C++沉思录》第0章——序幕后的一点想法,可以算作是笔记也可以算作是读后感。参加了这么多年NOIP,一直在使用C++ 语言,但由于平时写的代码都是100~300行的短代码,所以完全无法理解C++的类的意义。今日阅读Andrew Koenig大师的这部作品,虽然只阅读了寥寥数言,但对于类的理解顿时加深了许多。

正文

  让我们先假设一个情景。一位客户提出这样一个需求:编写一个程序输出Hello World!到屏幕。这个需求非常简单,任何一个学过一点C语言的人都可以迅速实现:

1 #include <stdio.h>
2 #include <stdlib.h>
3  
4 int main()
5 {
6     printf("Hello World!");
7  
8     return 0;
9 }

  但如果用C++的类来写,就要复杂得多。

01 #include <cstdio>
02 #include <cstdlib>
03  
04 class Output
05 {
06     public:
07         void print(char *str)
08         {
09             printf("%s",str);
10         }
11 };
12  
13 int main()
14 {
15     Output output;
16     output.print("Hello World");
17  
18     return 0;
19 }

  显而易见的是,C++的版本要复杂得多,那么,我们为什么要用C++?C++的优势何在?我们继续改动我们的程序。接下来,假设客户又增加了需 求,希望能输出多个字符串。于是,我们可以建立多个Output类型的变量,以适应需求变动。而C语言代码可以通过多个printf函数解决这次需求变 动。

  然后,客户目前的需求又有所改变:客户要求设计一个开关,可以控制是否输出字符串。针对这个需求变动,我们可以写出这样的C++代码:

01 #include <cstdio>
02 #include <cstdlib>
03  
04 class Output
05 {
06 public:
07     void print(char *str)
08     {
09         if(state)
10             printf("%s",str);
11     }
12     void setState(bool enabled)
13     {
14         state=enabled;
15     }
16 private:
17     bool state;
18     //If true, then output is enabled.
19     //Otherwise, output is disabled.
20 };
21  
22 int main()
23 {
24     Output output;
25     output.setState(true);
26     output.print("Hello World");
27  
28     return 0;
29 }

这样,所有的Output就都具有了开关。而C语言代码就需要一个相对规模较大的重构才可以应对这个变动的需求。

  从上面那个例子我们可以看出,同样的功能,无论是C还是C++往往都有能力去实现。不同点在于可维护性。前面的代码不断被修改的直接原因就在于需求变化。需求的不断变化才是问题的关键。 如果代码是一次性的,针对某一特定问题的,不会变化的,那么怎样实现都可以。在这方面很难体现出类的优势。这也是为什么写了这么多年的NOIP的题目,笔 者依旧难以深入理解类。题目是死的,没有需求上的变动。但大型软件不一样,它会随着时间的发展而发展,随着新需求的出现而不断变化。而且越大型的软件遇到 一次需求变动时,需要改动的代码可能就越多。而C++类便是针对这一问题的一种解决方案。有了类的抽象,需求的变动对代码的影响就减小了很多。这样,软件 的维护成本就被大规模地降低了。

  总而言之,C++的类是为了解决软件开发中不断的需求变化而生的。在必要的时候抽象具体的细节,以减小变化对代码造成的影响。这就是类的作用。

后记

  C++总被人认为是最难以精通的语言。它提供了大量特性,类、模板等等。但同时,它也保留了C语言的面向过程。它犹如一把瑞士军刀,提供了大量 的功能,是解决问题的利器。但同时,它也信任程序员能够恰当地选用合适的工具(瑞士军刀提供了很多工具)。根据具体的需求和可能的需求变动谨慎使用它,才 是正确的做法。例如在NOIP这类的程序中就不使用复杂的抽象,因为题目是死的,几乎没有需求变动。速度才是关键。一些功能清晰的小工具也不必使用太过复 杂的抽象,否则就是过度设计了。为不可能的变化而设计,也会增加软件开发的成本。而对于那些在可预见的时间内规模会迅速增长的程序,抽象就十分有必要了。 根据可预见的需求,使用恰当的程序语言表达,才是正确的。

  综上所述,我的思路好像还是不太清晰。[joke:)]

[转贴]关于C++的抽象的一点新认识的更多相关文章

  1. 最近使用Nginx的一点新得

    1.基本的负载配置 Nginx最简单的配置模块如下 upstream name{ server ip:port; server ip:port; } server { listen 80; serve ...

  2. python 中的一点新知识

    逻辑行与物理行 所谓物理行(Physical Line)是你在编写程序时 你所看到 的内容.所谓逻辑行(Logical Line)是 Python 所看到 的单个语句.Python 会假定每一 物理行 ...

  3. 工控PLC中,关于定时器TON,TOF,的一点新认知,或者说醒悟吧!

    PLC  中的定时器,都是放在一个具体PRG任务单元中的,而PRG单元需要放在具体固定的周期循环任务中才能被执行,而这个周期循环任务的循环周期 T: 与定时器的定时时间T0:    T与T0 的数量级 ...

  4. 译|调整JavaScript抽象的迭代方案

    原文作者:Kaloyan Kosev 原文链接:https://css-tricks.com/adapting-javascript-abstractions-time/ 翻译译者:小溪里 校对:华翔 ...

  5. 调整JavaScript抽象的迭代方案

    原文链接:Adapting JavaScript Abstractions Over Time 译者:小溪里 校对者:郭华翔.苗冬青 即使还没有读过我的文章<在处理网络数据的 JavaScrip ...

  6. C++默认构造函数的一点说明

    大多数C++书籍都说在我们没有自己定义构造函数的时候,编译器会自动生成默认构造函数.其实这句话我一直也是 深信不疑.但是最近看了一些资料让我有了一点新的认识. 其实我觉得大多数C++书籍之所以这样描述 ...

  7. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  8. Java-马士兵设计模式学习笔记-工厂模式-抽象工厂模式

    一.概述 1.抽象工厂:当情况是需要产生一系列产品,若需更换产品,则要求一系列产品一起换,且要控制一系列产品的产生过程,此时可考虑抽象工厂模式.例:小明装修屋子,把电视.冰箱都替换掉,他这次需要把电视 ...

  9. .NET项目开发—浅谈面向接口编程、可测试性、单元测试、迭代重构(项目小结)

    阅读目录: 1.开篇介绍 2.迭代测试.重构(强制性面向接口编程,要求代码具有可测试性) 2.1.面向接口编程的两个设计误区 2.1.1.接口的依赖倒置 2.1.2.接口对实体的抽象 2.2.迭代单元 ...

随机推荐

  1. 别了 oi——一篇高三狗的滚粗遗言

    /* 开始于2015年12月 结束于2016年11月 一年的oi生涯有很多值得怀念的事 还记得去年旺哥找我学oi 当时是一脸的蒙逼 要知道 高二才开始搞是很晚了 然而 也就是那一晚之后 许多事情都变了 ...

  2. 学点css之经验总结篇章

    学css说起来应该有三天左右的时间的,加上之前了解的基础,对css有一点的感性认识了,相应代码有有比较好的把握,现在就通过分享几张照片的形式分享一下我的收获 备注:在Border的外边的部门被称作:o ...

  3. PostgreSQL 修改列报错:cannot be cast automatically to type integer

    如果你直接使用可视化工具修改一个varchar字段为int类型的时候,可能会报错, 这里就需要自己去写一个语句去修改了 调整执行语句:ALTER TABLE table_name ALTER COLU ...

  4. 浅谈C#随机数发生器

    我们在做能自动生成试卷的考试系统时,常常需要随机生成一组不重复的题目,在.net Framework中提供了一个专门用来产生随机数的类System.Random. 对于随机数,大家都知道,计算机不 可 ...

  5. 将vs2012的项目转化成VS2010

    vs2012生成的项目,如何在只装有VS2010的电脑上打开, 步骤: 1.打开一个记事本,将你的Vs2012生成的项目解决方案文件(.sln文件)文件拖到记事本中 2.修改前两行  Microsof ...

  6. 20160408javaweb之JDBC ---PreparedStatement

    PreparedStatement 1.Sql注入:由于jdbc程序在执行的过程中sql语句在拼装时使用了由页面传入参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生变化,这种攻 ...

  7. SecurityException:Not allowed to start service Intent ,without permission not exported from

    本来是学长以前的项目,我正在重做一遍.结果突然出现了异常,我很是不解啊,怎么莫名其妙的就出现异常了呢?我昨天用还是好好的,根本就没动过源代码.于是在网上开始了一遍又一遍的查询,有的说要加权限.有的说这 ...

  8. addLoadEvent函数

    首先是addLoadEvent函数的代码清单: function addLoadEvent(func){    var oldonload=window.onload;    if(typeof wi ...

  9. jsp a标签传值到action中,action接收不到传值

    因为需求,今天在action中加了一个marker属性,尝试了很多方法 set,get方法也生成了,但是就接收不到值. 这时我注意到action中有我之前使用ajax请求数据返回json格式数据,不以 ...

  10. [翻译][MVC 5 + EF 6] 2:基础的增删改查(CRUD)

    原文:Implementing Basic CRUD Functionality with the Entity Framework in ASP.NET MVC Application 1.修改Vi ...