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. C++ STL (备忘)

    2014-08-04 16:33:57 (1)  map  map定义形式 map<type1,type2> map_name; map的基本操作函数:      C++ Maps是一种关 ...

  2. Java动态绑定

    1. 动态绑定 将一个方法调用同一个方法主体关联起来被称作绑定. 在运行时根据对象的类型进行绑定,叫做后期绑定或运行时绑定.Java中除了static方法和final 例如,下面定义了一个Shape类 ...

  3. C#微信公众号开发 -- (四)获取API调用所需的全局唯一票据access_token

    access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.access_token的存储至少要保留512个字符空间.access_to ...

  4. sqlite 数据库打开失败

    今天在做Android电子词典的时候,数据库打不开,报错为:Could not open the database in read/write mode. 后来才发现犯了一个低级错误,没有设置权限. ...

  5. MVC小系列(四)【向RouteData里扔数据】

    向RouteData里扔数据 当Url做路由之后,QueryString里当然是不可能再存你的信息了,而信息包括控制器,action,参数都会存储在RouteData里,而一般这里的信息都是通过前一个 ...

  6. MarkDown Pad2的一些用法

    一.标题 1.使用命令Ctrl+1 标题一 2.使用文字回车后,加上"-"号,再回车.就有如下的示例: 标题二 注意:减(-)号是用于最近的那一行文字变成标题. 二.背景 例如我要 ...

  7. Codevs 1697 ⑨要写信

    1697 ⑨要写信 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 琪露诺(冰之妖精)有操控冷气的能力.能瞬间冻结小东西,比 ...

  8. Android版多线程下载器核心代码分享

    首先给大家分享多线程下载核心类: package com.example.urltest; import java.io.IOException; import java.io.InputStream ...

  9. c# 与 winform 界面开发

    在 windows 下使用 vs2010 开发,未深入研究. c# 与 .net 开发,一堆又一堆的新名词,头晕目眩,比如 CLR / apartments / STA / MTA / COM 吐槽无 ...

  10. Entity Framework 的事务 DbTransaction

    事务代码实现如下: public static void Transaction() { myitEntities entity = null; DbTransaction tran = null; ...