C语言实现的OOP

我倒不是为了OOP而OOP,实在是OOP的一些特征,例如封装,多态其实是软件工程思想,这些思想不分语言,遵循了这些思想可以使得程序更有弹性,更易修改和维护,避免僵化,脆弱


shape.h 该文件定义的是图形接口,所有具体图形都必须实现自己计算面积,周长等API

#ifndef SHAPE_H

#define SHAPE_H



typedef struct shape_t 

{

    void *shapeData;

    void (*area)(void *);

    void (*release)(void *);

}Shape;



#endif

circle.h 圆形接口

#ifndef CIRCLE_H

#define CIRCLE_H



typedef struct

{

    double r;

}CircleData;



typedef struct 

{

    void *shapeData;

    void (*area)(void *);

    void (*release)(void *);

}Circle;



Circle *makeCircle(double r);



#endif

circle.c 圆形的实现代码,static修饰的函数其实相当于private函数

#include <assert.h>

#include <stdlib.h>

#include <stdio.h>

#include "circle.h"



const double PI = 3.14159;



static void area(void *shape)

{

    Circle *_circle = (Circle *)shape;

    CircleData* data = (CircleData*)_circle->shapeData;

    printf("the circle area is %f \n", data->r * data->r * PI);

}



static void release(void *shape)

{

    Circle *_circle = (Circle *)shape;

    CircleData* data = (CircleData*)_circle->shapeData;

    free(data);

    free(_circle);

}



Circle *makeCircle(double r)

{

    CircleData* circleData = (CircleData*)malloc(sizeof(CircleData));

    Circle* circle = (Circle*)malloc(sizeof(Circle));

    assert(circleData != NULL);

    assert(circle != NULL);

    assert(r > 0);



    

    circleData->r = r;

    circle->shapeData = circleData;

    circle->area = &area;

    circle->release = &release;



    return circle;

}

square.h

#ifndef SQUARE_H

#define SQUARE_H



typedef struct

{

    double x;

    double y;

}SquareData;



typedef struct 

{

    void *shapeData;

    void (*area)(void *);

    void (*release)(void *);

}Square;



Square *makeSquare(double x, double y);



#endif

square.c

#include <assert.h>

#include <stdlib.h>

#include <stdio.h>

#include "square.h"



static void area(void *shape)

{

    Square *square = (Square *)shape;

    SquareData* data = (SquareData*)square->shapeData;

    printf("the square area is %f \n", data->x * data->y);

}



static void release(void *shape)

{

    Square *square = (Square *)shape;

    SquareData* data = (SquareData*)square->shapeData;

    free(data);

    free(square);

}



Square *makeSquare(double x, double y)

{

    SquareData* squareData = (SquareData*)malloc(sizeof(SquareData));

    Square* square = (Square*)malloc(sizeof(Square));

    assert(squareData != NULL);

    assert(square != NULL);

    assert(x > 0 && y > 0);



    squareData->x = x;

    squareData->y = y;

    square->shapeData = squareData;

    square->area = &area;

    square->release = &release;



    return square;

}

main.c 所有的工作,都为了它,是为了让它的代码稳定

#include <stdio.h>

#include "shape.h"

#include "circle.h"

#include "square.h"



void printShapeArea(Shape **shape,int length)

{

    int i=0;

    for(i=0;i<length;i++)

    {

        shape[i]->area(shape[i]);

        shape[i]->release(shape[i]);

    }

}



int main()

{

    Shape *p[3] = {(Shape*)makeCircle(3.2),(Shape*)makeCircle(3.2),(Shape*)makeSquare(3.1,4)};

    printShapeArea(p,3);

    return 0;

}

 

总结:

printShapeArea 函数并不知道传入的图形列表分别都是哪些图形,这些图形又都怎么计算面积和周长,它唯一知道的是,这些图形计算面积和周长的接口是什么,通过这个接口计算就好了

 

你可能感兴趣的:(oop)