C++学习笔记:(七)C语言实现面向对象编程
面试官:C和C++有什么不同?
应聘者:一个是面向过程,一个是面向对象。
这样的答案在我看是不完全正确,因为面向过程编程和面向对象编程是编程思想,C++可以用面向过程的思想编程,同样,C语言也可以用面向对象的思想编程。可能很少有人想过用C语言实现面向对象编程(真的麻烦,感觉就是吃力不讨好),但是,通过这样的尝试,可以使我们的学习过程更有意思。也能通过用C语言实现面向对象编程来深化对封装、继承、多态的理解(这是我个人的感觉)。以下的例子可能过于简单或不够全面(只实现了一部分),如果想再深入研究,建议上网百度相关的知识。
在学习如何使用C语言完成面向对象编程之前,先来看函数指针的用法。
#include <stdio.h>
char (*p)(int);
char Fun(int a)
{return a;
}int main()
{p = Fun;printf("%c\n",(*p)(75));return 0;
}
复习了函数指针,接下来尝试用C语言中实现C++中的类,类似于:
class Asd
{public:int a,b;int finda(){return a;}int findb(){return b;}int ab(){return a+b;}
};
具体实现如下:
#include <stdio.h>
#include <malloc.h>
struct Asd;
struct Asd_option//Asd类的函数成员
{int (*get_a)(struct Asd*);int (*get_b)(struct Asd*);int (*ab)(struct Asd*);
};typedef struct Asd//Asd类
{int a;//公有数据成员 int b;//公有数据成员struct Asd_option *a_option;//函数指针,指向的是操作
}Asd;int finda(struct Asd *s)//具体操作
{return s->a;
}
int findb(struct Asd *s)
{return s->b;
}
int findab(struct Asd *s)
{return (s->a)+(s->b);
}struct Asd_option qwe_option =
{finda,findb,findab
};//函数指针赋值struct Asd Asd_create(int x, int y)//Asd类的构造函数
{struct Asd asd;asd.a = x;asd.b = y;asd.a_option = &qwe_option;return asd;
}int main()
{Asd a = Asd_create(1,2);int x = a.a_option->get_a(&a);int y = a.a_option->get_b(&a);int z = a.a_option->ab(&a);printf("X:[%d] Y:[%d] Z:[%d]\n", x,y,z);printf("Asd_a:[%d]\n", a.a);return 0;
}
在C语言中,结构体就能完成简单的封装。因为结构体中是不能像C++类那样声明函数成员,所以要使用函数指针完成这一部分的功能。
struct Asd_option qwe_option =
{finda,findb,findab
};
这就是通过结构体对函数指针赋值。这样使得Asd类既有数据成员,又有函数成员。
上面的例子完成了最简单的封装,而且数据成员都是公有的,接下来实现保护或私有数据成员,类似于:
class Asd
{
private:int x,y;
public:int a,b;int findx(){return x;}int findy(){return y;}int xy(){return x+y;}
};
#include <stdio.h>
#include <malloc.h>
struct Asd;
struct Asd_option//可以设为保护成员也可以设为私有成员
{int x;int y;int (*get_x)(struct Asd*);int (*get_y)(struct Asd*);int (*xy)(struct Asd*);
};typedef struct Asd//Asd类
{int a;int b;struct Asd_option *a_option;//函数指针
}Asd;int findx(struct Asd *s)//具体操作
{return s->a_option->x;
}
int findy(struct Asd *s)
{return s->a_option->y;
}
int findxy(struct Asd *s)
{return (s->a_option->x)+(s->a_option->y);
}struct Asd_option qwe_option =
{0,0,findx,findy,findxy
};//函数指针赋值Asd Asd_create(int m, int n)//Asd类的构造函数
{struct Asd asd;asd.a = 3;asd.b = 4;asd.a_option = &qwe_option;asd.a_option->x = m;asd.a_option->y = n;return asd;
}int main()
{Asd a = Asd_create(1,2);int x = a.a_option->get_x(&a);int y = a.a_option->get_y(&a);int z = a.a_option->xy(&a);printf("X:[%d] Y:[%d] Z:[%d]\n", x,y,z);printf("Asd_a:[%d]\n", a.a);printf("Asd_b:[%d]\n", a.b);//printf("Asd_x:[%d]\n", a.x); //printf("Asd_y:[%d]\n", a.y); //x,y保护(或私有)数据成员,不能直接访问return 0;
}
接下来实现简单的重载多态:
#include <stdio.h>
#include <stdlib.h>
typedef struct intasd
{int a;int b;
}Int_asd;typedef struct floatasd
{float x;float y;
}Float_asd;typedef void* (*Addfunction)(void*); //typedef定义函数指针的语法:typedef 返回类型 (*指针名)(参数表)void* intadd(void *asd)
{Int_asd *s = (Int_asd*)asd;int amount = s->a + s->b;printf("Result: = [%d]\n", amount) ;
}void* floatadd(void *asd)
{Float_asd *s = (Float_asd*)asd;float amount = s->x + s->y;printf("Result: = [%f]\n", amount) ;
}void* Add(Addfunction f, void *asd)
{return f(asd);
}int main()
{Int_asd x = {1, 2};Float_asd y = {1.1, 2.2};Add(intadd, &x);Add(floatadd, &y);return 0;
}
实现继承和包含多态:
#include <stdio.h>
#include <malloc.h>
#include <math.h>
struct Shape;
struct Shape_option
{float (*area)(struct Shape*);/*返回几何体的面积*/int (*perimeter)(struct Shape*);/*返回几何体的周长*/
};typedef struct Shape //基类
{char* Shape_name;struct Shape_option *Shape_ops; /*虚函数,功能由子类实现*/
}Shape;float Shape_area(struct Shape* s)/*求形状面积*/
{return s->Shape_ops->area(s);
}int Shape_perimeter(struct Shape* s) /*求周长*/
{return s->Shape_ops->perimeter(s);
}typedef struct triangle/*三角形类*/
{Shape Base;//公有继承int a;int b;int c;
}Triangle;float Triangle_area(struct Shape* s)/*三角形面积,用海伦公式*/
{Triangle *t = (Triangle*)s;int x = t->a;int y = t->b;int z = t->c;float p = (x+y+z)/2;return sqrt(p*(p-x)*(p-y)*(p-z));
}int Triangle_perimeter(struct Shape* s)/*三角形周长*/
{Triangle* t = (Triangle*)s;int x = t->a;int y = t->b;int z = t->c;return x+y+z;
}struct Shape_option triangle_ops =/*对父类虚函数的实现*/
{Triangle_area,Triangle_perimeter
};Triangle* Triangle_create(int x,int y,int z)/*三角形构造函数*/
{Triangle* ret = (Triangle*)malloc(sizeof (*ret));ret->Base.Shape_name = "triangle";ret->Base.Shape_ops = &triangle_ops;ret->a = x;ret->b = y;ret->c = z;return ret;
}typedef struct rectangle/*矩形类*/
{Shape Base;//公有继承int width;int height;
}Rectangle;float Rectangle_area(struct Shape* s)/*矩形函数成员*/
{Rectangle* r = (Rectangle*)s;return r->width * r->height;
}int Rectangle_perimeter(struct Shape* s)/*矩形函数成员*/
{Rectangle* r = (Rectangle*)s;return (r->width+r->height)*2;
}struct Shape_option rectangle_ops =/*对父类虚函数的实现*/
{Rectangle_area,Rectangle_perimeter
};Rectangle* Rectangle_create(int width, int height)/*矩形构造函数*/
{Rectangle* ret = (Rectangle*)malloc(sizeof(*ret));ret->Base.Shape_name = "rectangle";ret->Base.Shape_ops = &rectangle_ops;ret->height = height;ret->width = width;return ret;
}int main()
{Shape *s[4];s[0] = (Shape*)Triangle_create(5,5,4);s[1] = (Shape*)Triangle_create(3,4,5);s[2] = (Shape*)Rectangle_create(10,12);s[3] = (Shape*)Rectangle_create(5,8);int i=0;for(i=0 ;i<4 ;i++){float area = Shape_area(s[i]);int perimeter = Shape_perimeter(s[i]);char *name = s[i]->Shape_name;printf("name:%s ,area:%.2f ,perimeter:%d\n",name,area,perimeter);}return 0;
}
Shape是基类,Triangle类继承基类Shape,并新增数据成员a、b、c,实现简单的继承。上述例子中,子类对父类虚函数进行实现,实现了包含重载。虽然上面的结果可能不能像C++所展示的那样,但是思想上是面向对象的。
运算符重载将重载的概念扩展到运算符上,允许赋予C++运算符多种含义。实际上,C++(包括C语言)运算符已经被重载。例如,将*运算符用于地址,将得到存储在这个地址中的值;但将它用于两个数字时,得到的将是他们的乘积。
参考:http://blog.chinaunix.net/uid-26921272-id-3360269.html
C++学习笔记:(七)C语言实现面向对象编程相关推荐
- JavaScript学习笔记(十一):面向对象编程
一.关于面向对象 编程可以分为面向过程编程和面向对象编程 面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用 面向对象:把一件事分解成一个个对象 ...
- 《objective-c基础教程》学习笔记(四)—— OC面向对象编程初探
在上篇博文中,我们编写了一个可以输出不同几何类型的小程序.通过C语言的struct结构体,给大家感受了下,对象的大概样子. 如果用Obejctive-C的面向对象的特征来实现.那么,drawShape ...
- 2022Java学习笔记八十八(网络编程:UDP通信,一发一收,多发多收消息接收实现)
2022Java学习笔记七十八(网络编程:UDP通信,一发一收,多发多收消息接收实现) 一.快速入门 DatagramPacket:数据包对象 实例代码 定义发送端 package com.zcl.d ...
- 23 DesignPatterns学习笔记:C++语言实现 --- 2.2 Adapter
23 DesignPatterns学习笔记:C++语言实现 --- 2.2 Adapter 2016-07-22 (www.cnblogs.com/icmzn) 模式理解 1. Adapter 定义 ...
- Java快速入门学习笔记9 | Java语言中的方法
有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...
- Java快速入门学习笔记7 | Java语言中的类与对象
有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...
- 逆向脱壳破解分析基础学习笔记七 堆栈图(重点)
本文为本人 大神论坛 逆向破解脱壳学习笔记之一,为本人对以往所学的回顾和总结,可能会有谬误之处,欢迎大家指出. 陆续将不断有笔记放出,希望能对想要入门的萌新有所帮助,一起进步 堆栈图 首先给定一段反汇 ...
- 【学习笔记】C++语言程序设计(郑莉):多态性
[学习笔记]C++语言程序设计(郑莉):多态性 1. 多态性 2. 运算符重载 2.1 运算符重载的规则 2.2 运算符重载为成员函数 2.3 运算符重载为非成员函数 3. 虚函数 3.1 一般虚函数 ...
- Python学习笔记(十九)面向对象 - 继承
Python学习笔记(十九)面向对象 - 继承 一.继承的概念 # 继承:子类继承父类的所有方法和属性# 1. 子类 class A(object):def __init__(self):self.n ...
最新文章
- 中体骏彩C++面试题
- AMS重要的数据结构解析(三):ActivityStack
- 皮一皮:成人世界的潜台词...
- 【MM模块】Releasing Blocked Invoices 释放冻结发票
- 推荐系统——开源代码
- 【Mongodb】用户和认证 权限总结
- scipy是python下的什么_SciPy是什么
- 计算机数学基础模拟试题,计算机数学基础》模拟考试试题.doc
- 551. 学生出勤记录 I
- C++学习日记#3——追赶法求解系数矩阵为对角占优的三对角线方程组
- 雷士灯wifi控制方法_雷士照明驱动 WiFi 可调光 怎么设置
- 小小技巧--BLOB视频加密
- DIV+CSS学习笔记总结篇
- 《30天自制操作系统》-day2(MAC)
- Unbuntu20.04环境下一款开源翻译软件:goldendict的安装与配置(图文)
- 【人工智能】人脸识别系统【实验报告与全部代码】(QDU)
- 为任意屏幕尺寸构建 Android 界面
- KnockoutJs 进阶学习
- PDF合并:如何将两个PDF文件合并成一个PDF文件
- 适用于异构芯片(CPU,ASIC,DSP,FPGA,GPU)的软件并行技术