1. 基本知识

1.1 结构体

1.2 函数指针

1.3 #ifndef

作用:① 头文件中使用,防止头文件被多重调用;② 作为测试使用,省去注释代码的麻烦;③ 作为不同角色或者场景的判断使用。。
使用:把头文件的内容都放在#ifndef和#endif中

#ifndef <标识>
#define <标识>......
......#endif

解释:<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H_
#define _STDIO_H_......#endif

2. C语言实现封装

封装的含义是隐藏内部的行为和信息,使用者能看到对外提供的接口和公开的信息。
实现方法:

2.1 头文件中声明,CPP文件中定义

这样可以隐藏内部信息,因为外部不知道对象所占内存的大小,所以不能静态的创建该类的对象,只能调用类提供的创建函数才能创建。这种方法的缺陷是不支持继承,因为子类中得不到任何关于父类的信息。
//point.h文件

#ifndef POINT_H
#define POINT_H
struct Point;
Point* new_Point(double x,double y); //创建一个新对象
void free_Point(Point* Point_);//释放一个对象
#endif

//point.cpp文件

#include"point.h"
#include <stdlib.h>
#include <stdio.h>
struct Point
{double x;double y;
};Point* new_Point(double x, double y)
{Point* p = (Point*)malloc(sizeof(Point));//(指针类型)变量名=(指针类型)malloc(n * sizeof(类型)——(指针类型)强转为同变量类型;                                           p->x = x;p->y = y;printf("%s\n","创建新对象");return p;
}void free_Point(Point* Point_)
{if (Point_ == NULL)return;else{printf("%s\n","释放对象");free(Point_);}
}

//主程序中

#include <iostream>
#include"point.h"
#include"stdio.h"
int main()
{Point* p1;p1 = new_Point(4.5, 5.5);free_Point(p1);return 0;
}

这样使用point.h 的程序就不知道 Point 的内部结构,实现了数据的封装,外部只能使用声明的两个函数

2.2 私有数据放在不透明的priv变量或者结构体中。

如此操作,只有类的实现代码才知道priv或者结构体的真正定义
//point.h文件中

#ifndef POINT _H#define POINT_Htypedef struct Point point;typedef struct PointPrivate pointPrivate;struct Point
{struct pointPrivate *pp;
};double get_x(point* point_);double get_y(point* point_);point* new_point(double x_,double y_); //创建新对象void free_point(point* point_);// 释放对象#endif
//point.cpp文件中#include"point.h"
#include"stdlib.h"//malloc的头文件
#include"stdio.h"
struct pointPrivate
{double x;double y;
};
double get_x(point* point_)
{return point_->pp->x;
}
double get_y(point* point_)
{return point_->pp->y;
}
point* new_point(double x_, double y_)
{pointPrivate* p1 = (pointPrivate*)malloc(sizeof(pointPrivate));p1->x = x_;p1->y = y_;point* p2= (point*)malloc(sizeof(point));p2->pp = p1;printf("%s\n","构造对象");return p2;
}
void free_point(point* point_)
{if (point_ == NULL)return;else{free(point_);printf("%s\n", "释放对象");}
}

//主程序中

#include <iostream>
#include"point.h"
#include"stdio.h"
using namespace std;
int main()
{point* p=new_point(4.5, 5.5);double a=get_x(p);double b = get_y(p);printf("%f%s%f\n",a,"  ",b);free_point(p);return 0;
}

3. C语言实现继承

C语言实现继承是通过结构体嵌套实现的。

4. C语言实现多态

5. 以例说明

5.1 Person.h

typedef struct Person person;
typedef struct Person_act person_act;//虚函数表结构
struct Person_act
{void(*eat)(void*);void(*drink)(void*);
};//基类
struct Person
{person_act* per_act;//人的基本行为
};void person_eat(void* thi);
void person_drink(void* thi);person* person_init();//构造函数
void person_die(person* per);//析构函数

说明:
C语言实现多态需要借助自定义的虚函数表结构体,结构体中为虚函数指针,表示需要实现多态的虚函数;
结构体Person为定义的基类,并自定义构造函数和析构函数。

5.2 Person.cpp

#include"Person.h"
#include"stdlib.h"
#include"string.h"
#include"stdio.h"void person_eat(void* thi)
{printf("person eat\n");
}void person_drink(void* thi)
{printf("person drink\n");
}person_act p_act = {person_eat,person_drink};//构造函数,需要显示调用
person* person_init()
{person* temp_per = (person*)malloc(sizeof(person_act));temp_per->per_act = &p_act;return temp_per;
}//析构函数,需要显示调用
void person_die(person* per)
{if (per == NULL)return;elsefree(per);
}

说明:
在cpp文件中定义构造函数和析构函数,但是在实际使用时,不像类一样自动调用,需要人为显示调用。
在构造函数中,将实际的函数写入其中,作为此结构体的”虚函数“。

5.3 Worker.h

#pragma once
#include"Person.h"
typedef struct Worker worker;
typedef struct Workerprivate workerprivate;//派生类
struct Worker
{Person person_base;//基类workerprivate* worker_info;//派生类信息
};void worker_eat(void* thi);
void worker_drink(void* thi);
worker* worker_init(const int num);//构造函数
void worker_die(worker* wor);
int get_num(worker* wor);

说明:
定义派生类worker,将基类Person的对象作为结构体的成员实现派生,注意需要将其写在本结构体自身成员的前面——实现继承。
另外,此处将派生类的成员信息重新定义一个结构体,其声明放在.h文件中,定义放在.cpp文件中,实现数据的封装。在.h文中列下接口函数get_num,作为外部函数接口,访问数据。

5.4 Worker.cpp

#include"Worker.h"
#include"stdlib.h"
#include"stdio.h"
#include"string.h"
struct Workerprivate
{int num;
};void worker_eat(void* thi)
{printf("worker eat\n");
}void worker_drink(void* thi)
{printf("worker drink\n");
}person_act w_act = {worker_eat,worker_drink};worker* worker_init(const int num)
{int num_len = sizeof(num);worker* temp_wor = (worker*)malloc(sizeof(person)+sizeof(Workerprivate));temp_wor->person_base.per_act = &w_act;Workerprivate* temp_info = (Workerprivate*)malloc(sizeof(Workerprivate));temp_info->num = num;temp_wor->worker_info = temp_info;return temp_wor;
}int get_num(worker* wor)
{return wor->worker_info->num;
}

说明:
此处定义的结构体:Workerprivate是为了实现数据封装,在此处定义。并在cpp文件中重新定义其对应的虚函数,将其在构造函数中写入worker对应的结构体。
get_num是结构体对外的接口函数,用来访问其”私有数据“——num

5.5 测试程序

#include <iostream>
#include"Person.h"
#include"Worker.h"
#include"stdlib.h"
int main()
{//基类测试person* person1 = person_init();person1->per_act->drink((void*)person1);person1->per_act->eat((void*)person1);//派生类测试worker* worker1 = worker_init(202015);//printf("%d\n",worker1->worker_info.num);//直接访问数据不可以,实现了数据封装int temp_num = get_num(worker1);printf("%d\n", temp_num);worker1->person_base.per_act->drink((void*)worker1);worker1->person_base.per_act->eat((void*)worker1);//多态测试person* person2 = person_init();worker* worker2= worker_init(202016);person2 = (person*)worker2;//基类指针指向派生类对象person2->per_act->drink(person2);person2->per_act->eat(person2);
}

说明:
基类测试:实例化基类对象,并通过基类对象调用其对应的函数
派生类测试:实例化派生类对象,直接用对象访问其数据成员num不可以,实现了数据封装;但可以通过函数get_num访问其数成员。另外,可以通过派生类对象调用其自身的函数。
多态测试:多态是指函数会根据指针的内容决定调用哪个函数,而不是根据指针的类型决定。通过基类指针指向派生类对象,调用时仍是调用派生类的函数,不是调用基类的函数——即实现了虚函数的功能。

5.6 程序运行结果

5.7 总结

所有有c++编码规范的公司,都会对指针有大篇幅的约束,因为指针无所不能,刚才也看到了,就连程序的基础运行都依赖指针
虚函数表结构体也是通过指针实现

用C语言实现C++中类的封装继承多态相关推荐

  1. c语言编程 菲薄拉,C语言设计模式-封装-继承-多态

    快过年了,手头的工作慢慢也就少了,所以,研究技术的时间就多了很多时间,前些天在CSDN一博客看到有大牛在讨论C的设计模式,正好看到了,我也有兴趣转发,修改,研究一下. 记得读大学的时候,老师就告诉我们 ...

  2. Java继承_Hachi君浅聊Java三大特性之 封装 继承 多态

    Hello,大家好~我是你们的Hachi君,一个来自某学院的资深java小白.最近利用暑假的时间,修得满腔java语言学习心得.今天小宇宙终于要爆发了,决定在知乎上来一场根本停不下来的Hachi君个人 ...

  3. python 参数类型的多态_【Python】面向对象:类与对象\封装\继承\多态

    六.Python面向对象--类与对象\封装\继承\多态 1.什么是面向对象编程 1.1 程序设计的范式:程序可控,易于理解 1.2 抽象并建立对象模型 1.3 程序是不同对象相互调用的逻辑.每个对象在 ...

  4. 大数据笔记8—java基础篇4(面向对象-封装-继承-多态)

    面向对象 一.面向对象 1.面向过程 1.2.举例 1.3.总结 二.面向对象 1.简述 2.举例 3.思想特点 2.1.类的定义格式 2.1.1.简述 2.2.2.格式 2.3.3.示例 三.类的使 ...

  5. python多态的三种表现形式_python小结----面向对象的三大特征(封装,继承,多态)

    面向对象的三大特征: 封装,继承,多态 面向对象的编程思想核心:高类聚,低耦合–程序的设计模式范畴 封装 什么是封装: 在面向对象编程的思想中,对代码进行高度封装,封装又叫包装 封装就是指将数据或者函 ...

  6. python--编写程序:实现乐手弹奏乐器,乐手可以弹奏不同的乐器而发出不同的声音------使用类的封装继承多态的问题/使用面向对象的思想,设计自定义类,描述出租车和家用轿车的信息

    编写程序:实现乐手弹奏乐器,乐手可以弹奏不同的乐器而发出不同的声音 ------使用类的封装继承多态的问题 class Instrumnet():#乐器类def make_sound(self):pa ...

  7. 小白理解——封装继承多态

                                      一.封装 是什么:首先是抽象,把事物抽象成一个类,其次才是封装.对外表示为一个对象,隐藏对象的属性和动作实现的细节,仅对外公开接口. ...

  8. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态

    Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...

  9. 面向对象 编程及面向对象三大属性:封装 继承 多态

    面向对象 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构.应用平台.分布式系统.网络管理结构. ...

  10. 白话文带你了解 封装 继承 多态

    这里讲的仅仅是带你理解 封装 继承 多态 染好您可以移步去别的文章学习具体的实现 (只是个人理解 您可以不爱,请别伤害哦!) 首先你要知道 java是面向对象的,说白了就是我拿你当个人,请认清你的地位 ...

最新文章

  1. 智能计算机和智能化网络结论,人工智能技术中计算机网络技术的应用
  2. 【Android工具】Cx文件管理器,Cx File Explorer安卓samba客户端
  3. 上学路线 (Standard IO)
  4. 方法引用_通过类名引用静态成员方法
  5. python 指针指向的内容,python-文件的读取及指针位置
  6. linux中开启snmp协议
  7. mamp安装php扩展,mac版mamp下php安装pcntl扩展
  8. word-wrap和word-break
  9. 骆昊python100天百度云_GitHub - Luffy-cc/Python-100-Days: Python - 100天从新手到大师
  10. 基于IPFS视频存储的在线视频网站
  11. 小达同学软件测试第三讲
  12. mysql jdbc execute_MySQL JDBC Statement.executeBatch实践问题
  13. HCIE(M-LAG)
  14. java丐帮_java包的问题
  15. 燕京理工学院计算机答辩难吗,燕京理工学院:一腔热血答与辩,满腹经纶方成功...
  16. 09、查询详细信息和删除记录
  17. 完美解决“The identity used to sign the executable is no longer valid.”问题
  18. Incorrect username or password ( access token )
  19. iOS学习—iOS长按手势事件
  20. Centos 7下Nagios的安装及配置(完整版)

热门文章

  1. Flutter RotatedBox旋转容器
  2. 微信小程序自定义组件(Toast)
  3. java 自动装载_JAVA反射技术之自动装载/自动验参
  4. java native方法_深入理解Java虚拟机
  5. org.gradle.api.tasks.compile.CompileOptions.setBootClasspath
  6. 可编译运行的安卓USB/OTG摄像头程序
  7. WIN7上安装OFFICE 2019(未成功)
  8. LINUX编译OpenJDK,也可以指定freetype
  9. 大型太阳能电池板在卫星上的使用,目前没有查到
  10. 遇到一个难题:如何从java中调用到C的功能