[转贴]关于C++的抽象的一点新认识 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:)]