面向对象(object oriented, OO),面向对象编程(object-oriented programming, OOP),以及面向对象编程语言(object-oriented programming languages, OOPL)的定义多种多样。想了解我对 OO 的详细看法,请阅读 C++ 为什么不仅仅是面向对象的语言。我在那里写道,OOP 这种编程风格起源于 Simula(约 40 年以前!),它依赖于封装(encapsulation)、继承(inheritance)以及多态(polymorphism)。就 C++(及许多其它源于 Simula 的语言)而言,OOP 的意思是利用类层级(class hierarchies)及虚函数进行编程,从而可以通过精制的接口操作各种类型的对象,并且程序本身也可以通过派生(derivation)进行功能增量扩展。
你可以从类的伟大之处是什么这篇文章了解到“普通类(plain classes)”的伟大之处。把多个类组织成类层级是为了表达类之间的层次关系并且利用这些关系简化代码。
要想真正理解 OOP,就要看些例子。例如,你可能有两个(或者更多)设备驱动共用一个公共接口:
class Driver { // 公共驱动接口
public:
virtual int read(char* p, int n) = 0; // 从设备中读取最多 n 个字符到 p
// 返回读到的字符总数
virtual bool reset() = 0; // 重置设备
virtual Status check() = 0; // 读取状态
};
Driver 仅仅是一个接口。它没有任何数据成员,而其成员函数都是纯虚函数。通过这些接口就可以使用某个驱动;不同类型的驱动负责对这个接口进行相应的实现:
class Driver1 : public Driver { // 某个驱动
public:
Driver1(Register); // 构造函数
int read(char*, int n);
bool reset();
Status check();
// 实现细节
};
class Driver2 : public Driver { // 另一个驱动
public:
Driver2(Register);
int read(char*, int n);
bool reset();
Status check();
// 实现细节
};
注意,这些驱动含有数据成员,可以通过它们创建对象。它们实现了 Driver 中定义的接口。不难想象,可以通过这种方式使用某个驱动:
void f(Driver& d) // 使用驱动
{
Status old_status = d.check();
// ...
d.reset();
char buf[512];
int x = d.read(buf,512);
// ...
}
这里的重点是,f() 不需要知道它使用的是何种类型的驱动;它只需知道有个 Driver 传递给了它;也就是说,有一个接口传递给了它。我们可以这样调用 f() :
void g()
{
Driver1 d1(Register(0xf00)); // create a Driver1 for device
// with device register at address 0xf00
Driver2 d2(Register(0xa00)); // create a Driver2 for device
// with device register at address 0xa00
// ...
int dev;
cin >> dev;
if (dev==1)
f(d1); // use d1
else
f(d2); // use d2
// ...
}
注意,当 f() 使用某个驱动时,与该驱动相对应的操作会在运行时被隐式选择。例如,当 f() 得到 d1 时,d.read() 使用的是 Driver1::read();而当 f() 得到 d2 时,d.read() 使用的则是 Driver2::read()。这被称为运行时调度或者动态调度。本例,f() 无法得知调用的是何种设备,因为那是根据输入选择的。
请注意,OOP 并非万能药。不要简单地把“OOP”等同于“好”。如果你的问题的基本要素中没有与生俱来的层级关系,那么类层级和虚函数对你的代码不会有任何帮助。OOP 的优势在于类层级可以有效地表达很多问题;OOP 的主要弱点在于太多人设法强行用层级模式解决问题。并非所有问题都应该面向对象。也可以考虑使用普通类(plain class)、泛型编程和独立的函数(就像数学、C,以及 Fortran 中那样)作为解决问题的方案。
原文地址:http://www.research.att.com/~bs/bs_faq.html#oop
本文版权归 蚂蚁的 C/C++ 标准编程 以及 作者 Bjarne Stroustrup 翻译:antigloss 共同所有,转载请注明原作者和出处。谢谢。