#include "namedPoint.h"#include <stdlib.h>struct NamedPoint { double x,y; char* name;};struct NamedPoint* makeNamedPoint(double x, double y, char* name) { struct NamedPoint* p = malloc(sizeof(struct NamedPoint)); p->x = x; p->y = y; p->name = name; return p;}void setName(struct NamedPoint* np, char* name) { np->name = name;}char* getName(struct NamedPoint* np) { return np->name;}<b>main.c</b>#include "point.h"#include "namedPoint.h"#include <stdio.h>int main(int ac, char** av) { struct NamedPoint* origin = makeNamedPoint(0.0, 0.0, "origin"); struct NamedPoint* upperRight = makeNamedPoint (1.0, 1.0, "upperRight"); printf("distance=%f\n", distance( (struct Point*) origin, (struct Point*) upperRight));}Внимательно рассмотрев основной код в файле
main.cNamedPointPointNamedPointPointNamedPointPointNamedPointPointPointЭтот прием широко применялся [15] программистами до появления ОО. Фактически именно так C++ реализует единственное наследование.
То есть можно сказать, что некоторая разновидность наследования у нас имелась задолго до появления языков ОО. Впрочем, это утверждение не совсем истинно. У нас имелся трюк, хитрость, не настолько удобный, как настоящее наследование. Кроме того, с помощью описанного приема очень сложно получить что-то похожее на множественное наследование.
Обратите также внимание, как в
main.cNamedPointPointСправедливости ради следует отметить, что языки ОО действительно сделали маскировку структур данных более удобной, хотя это и не совсем новая особенность.
Итак, мы не можем дать идее ОО ни одного очка за инкапсуляцию и можем дать лишь пол-очка за наследование. Пока что общий счет не впечатляет.
Но у нас есть еще одно понятие.
Полиморфизм?
Была ли возможность реализовать полиморфное поведение до появления языков ОО? Конечно! Взгляните на следующую простую программу copy на языке C.
#include <stdio.h>void copy() { int c; while ((c=getchar())!= EOF) putchar(c);}Функция
getchar()STDINSTDINputchar()STDOUTSTDINSTDOUTВ некотором смысле
STDINSTDOUTgetchar()Ответ на этот вопрос прост: операционная система UNIX требует, чтобы каждый драйвер устройства ввода/вывода реализовал пять стандартных функций [16]:
openclosereadwriteseekСтруктура FILE имеет пять указателей на функции. В нашем случае она могла бы выглядеть как-то так:
struct FILE { void (*open)(char* name, int mode); void (*close)(); int (*read)(); void (*write)(char); void (*seek)(long index, int mode);};Драйвер консоли определяет эти функции и инициализирует указатели на них в структуре FILE примерно так:
#include "file.h"void open(char* name, int mode) {/*…*/}void close() {/*…*/};int read() {int c;/*…*/ return c;}