前言
作为高级语言,C已经很强大了,能够处理许多问题。
但是为什么还需要C++,C++出现的理由是什么,C++相比于C强大的核心本质在哪里?
一、类
#include<stdio.h>
class Trace{
public:
void print(char*s){printf("%s",s);}
};
int main(){
Trace t;
t.print("begin main()\n");
t.print("end main()\n");
}
- C++的核心概念是类。如上所示,定义了一个Trace类,用来实现跟踪输出的功能。
- 但是,上述代码所示的类,起到的作用并不大,我直接
printf
作用是相同的,甚至效率可能更好。
二、改进,实现关闭跟踪输出的功能
#include<stdio.h>
class Trace{
public:
Trace(){noisy=0;}
void print(char*s){if(noisy)printf("%s",s);}
void on(){noisy=1;}//开启输出
void off(){noisy=0;}//关闭输出
private:
int noisy;
};
int main(){
Trace t;
t.print("begin main()\n");
t.print("end main()\n");
}
- 在改进后的代码中,加入了私有成员
noisy
和void on()
、void off()
两个函数实现关闭和开启跟踪输出功能。 - 这个改进就有了很大的变化。如果我在程序中写了多次跟踪输出,遍布程序各个位置。当我不需要跟踪输出时,我可以使用
void off()
函数来实现。倘若不是这样,而是在程序中直接使用printf()
函数的话,我将要搜索程序,大面积更改程序内容。
三、改进,实现跟踪输出到不同设备的功能
#include<stdio.h>
class Trace{
public:
Trace(){noisy=0;f=stdout;}
Trace(FILE* ff){noisy=0;f=ff;}
//实现输出到不同设备,printf(args)与fprintf(stdout,atgs)等效
void print(char*s){
if(noisy){
fprintf(f,"%s",s);
}
}
void on(){noisy=1;}//开启输出
void off(){noisy=0;}//关闭输出
private:
int noisy;
FILE* f;
};
int main(){
Trace t(stderr);
t.print("begin main()\n");
t.print("end main()\n");
}
- 在上面的改进中,我们实现了输出到不同设备的功能。
- 倘若我们没有使用类,而是直接使用的
fprintf()
,那么就很难实现输出到不同设备的更改了。或许定义一个变量FILE* 然后要输出的不同设备时更改这个变量就行了,但是这样就很难实现不同代码段输出到不同设备的功能。而类只需要生成不同的类对象。
四、不用类来实现上述功能
#include<stdio.h>
static int noisy=1;
void trace(char*s){
if(noisy){printf("%s",s);}
}
void on(){noisy=1;}//开启输出
void off(){noisy=0;}//关闭输出
int main(){
trace("begin main()\n");
trace("end main()\n");
}
- 函数
trace()
不是内联的,使用它会有函数调用开销。 - 引入了四个全局变量trace、on、off、noisy。而使用类只产生一个全局变量。
- 很难实现将上述跟踪输出到不同的文件中。一个可能的实现方式是将trace增加一个参数,改成
void trace(FILE* ff,char* s)
。但是这样,如果以前前期没有考虑到,就需要更改大量的前期代码,或者写一个新函数trace_out()。
C++优秀的面向对象的核心本质
- C++使用类来存储辅助的状态信息,比如noisy,比如FILE。这方便后期的修改和维护。
- 对于C,倾向于不添加状态信息,而是在前期就规划好,这会造成后期维护苦难。
- C++将通过使用对象,将状态和动作进行绑定。所以就实现了具体到是谁做了什么动作,这个谁就具有自己的状态信息,根据状态信息完成不同的动作。
参考资料
[1]凯尼格. C++沉思录[M]. 北京 : 人民邮电出版社, 2002