问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何用C语言实现面向对象

发布网友 发布时间:2022-04-22 06:50

我来回答

10个回答

热心网友 时间:2022-04-12 22:38

可以通过以下方法实现面向对象:

1、封装

封装就是把数据和方法打包到一个类里面。其实C语言编程者应该都已经接触过了,C 标准库 中的 fopen(), fclose(), fread(), fwrite()等函数的操作对象就是 FILE。

数据内容就是 FILE,数据的读写操作就是 fread()、fwrite(),fopen() 类比于构造函数,fclose() 就是析构函数。

2、继承

继承就是基于现有的一个类去定义一个新类,这样有助于重用代码,更好的组织代码。在 C 语言里面,去实现单继承也非常简单,只要把基类放到继承类的第一个数据成员的位置就行了。

例如,我们现在要创建一个 Rectangle 类,我们只要继承 Shape 类已经存在的属性和操作,再添加不同于 Shape 的属性和操作到 Rectangle 中。

3、多态 C++

语言实现多态就是使用虚函数。在 C 语言里面,也可以实现多态。 现在,我们又要增加一个圆形,并且在 Shape 要扩展功能,我们要增加 area() 和 draw() 函数。

但是 Shape 相当于抽象类,不知道怎么去计算自己的面积,更不知道怎么去画出来自己。而且,矩形和圆形的面积计算方式和几何图像也是不一样的。

4、虚表和虚指针

虚表(Virtual Table)是这个类所有虚函数的函数指针的集合。

虚指针(Virtual Pointer)是一个指向虚表的指针。这个虚指针必须存在于每个对象实例中,会被所有子类继承。

5、在构造函数中设置vptr

在每一个对象实例中,vptr 必须被初始化指向其 vtbl。最好的初始化位置就是在类的构造函数中。

事实上,在构造函数中,C++ 编译器隐式的创建了一个初始化的vptr。在 C 语言里面, 我们必须显示的初始化vptr。下面就展示一下,在 Shape 的构造函数里面,如何去初始化这个 vptr。

热心网友 时间:2022-04-12 23:56

面向对象的三个基本特征是:封装、继承、多态。
--------------------------------------------------------------------------------------
C语言编程中常用的“面向对象”方法

其实C语言诞生以来,人们就想了很多办法来体现“面向对象”的思想。
1. 宏定义:
有的人不禁要问,宏定义怎么扯到这里来了,我们可以先看一个简单的例子:
#define MacroFunction Afunction
然后在程序里面你调用了大量的AFunction,但是有一天,你突然发现你要用BFunction了,(不过AFunction又不能不要,很有可能你以后还要调用),这个时候,你就可以#define MacroFunction Bfunction来达到这样的目的。
当然,不得不说这样的办法是too simple,sometime naïve的,因为一个很滑稽的问题是如果我一般要改为BFunction,一半不变怎么办? 那就只好查找替换了。
2. 静态的入口函数,保证函数名相同,利用标志位调用子函数:
这样的典型应用很多,比如说网卡驱动里面有一个入口函数Nilan(int FunctionCode,Para*)。具体的参数是什么记不清楚了。不过NiLan的主体是这样的:
Long Nilan(int FunctionCode,Para*){
Switch(FunctionCode){
Case SendPacket: send(….)
Case ReceivePacket: receive(…)
…..
}

写到这里大家明白什么意思了吧。保证相同的函数名就是说:网卡驱动是和pNA+协议栈互连的,那么如何保证pNA+协议栈和不同的驱动都兼容呢,一个简单的办法就是仅仅使用一个入口函数。通过改变如果函数的参数值,来调用内部的各个函数。这样的做法是可以进化的:如果以后想调用新的函数,增加相应的函数参数值就好了。如果我们将网卡驱动和pNA+协议栈看作两个层的话,我们可以发现:
层与层之间的互连接口是很小的(这里是一个入口函数),一般是采用名字解析的办法而不是具体的函数调用(利用FunctionCode调用函数,Nilan仅仅实现名字解析的功能)!
3.CALLBACK函数。
虽然它很简单,就象如何把鸡蛋竖起来一样,但是你如果没想到的话,嘿嘿。如果说静态入口函数实现了一个可管理的宏观的话,CallBack就是实现了一个可进化的微观:它使得一个函数可以在不重新编译的情况下实现功能的添加!

4.Event和Message
为了提高程序的灵活性,Event和Message的办法产生了。用名字解析的办法代替通常的函数调用,这样,如果双方对这样的解析是一致的话,就可以达到一个统一。不过Event和Message的作用还不仅仅是如此。
Event和Message还有建立进程间通信的功能。进程将自己的消息发给“控制中心”(简单的就是一个消息队列,和一个while循环不断的取消息队列的内容并执行),控制程序得到消息,分发给相应的进程,这样其他进程就可以得到这个消息并进行响应。

热心网友 时间:2022-04-13 01:30

面向对象本身是一种思想,而用哪种语言实现只是一种技术手段。事实上思想和技术的关系本身就是class和object的关系。

class oo {
//这是面向对象的思想类
}; 
oo java; //java是oo的一个具体的技术实现
oo cxx; //c++是oo的一个具体的技术实现

拿Windows系统来讲,它是有C语言编写的,但是使用的却是面向对象的思想,这方面可以参考reactos(一个免费开源的用于大学教授操作系统原理的windows系统)。


举一个例子也许更实际一些,比如,操作系统有两种操作界面,一种是GUI界面,一种是控制台界面,在windows平台上编写一个程序,在cmd中运行时,执行控制台界面的代码,在GUI中运行的时候,执行图形界面的代码。这实际上也算是一种面向对象编程中的多态实例。以下示例代码在vc6.0编译通过。

#include <stdio.h> 
#include <tchar.h>
#include <windows.h>
#include <TLHELP32.H>
char what_shell_run()
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap==0){
return _T('E');
}
PROCESSENTRY32 pe32 = {0};
pe32.dwSize = sizeof pe32;
DWORD dwSelfPid = GetCurrentProcessId();
DWORD dwParentPid = ~0;
for (BOOL bLoop=Process32First(hSnap, &pe32); bLoop!=FALSE; bLoop=Process32Next(hSnap, &pe32))
{
if (dwSelfPid==pe32.th32ProcessID){
dwParentPid = pe32.th32ParentProcessID;
break;
}
}
if (dwParentPid==~0) return _T('U');
for (bLoop=Process32First(hSnap, &pe32); bLoop!=FALSE; bLoop=Process32Next(hSnap, &pe32))
{
if (dwParentPid==pe32.th32ProcessID){
if (lstrcmpi(pe32.szExeFile, _T("cmd.exe"))==0)
{
CloseHandle(hSnap);
return _T('C');
}else if (lstrcmpi(pe32.szExeFile, _T("explorer.exe"))==0){
CloseHandle(hSnap);
return _T('G');
}
}  
}
CloseHandle(hSnap);
return _T('U');
}
void console(void) {
printf("这是一控制台程序\n");
}
void gui (void) {
MessageBox(0, _T("这是一个GUI程序"), _T("GUI"), MB_OK);
}
int main()
{
char ch = what_shell_run();
switch (ch)
{
case 'C':
console();break;
case 'G':
gui(); break;
}
return 0;
}

在cmd中运行该程序的结果:

在GUI界面运行该程序的结果:

热心网友 时间:2022-04-13 03:22

C确实可以实现面向对象,这点在linux中体现的淋漓尽致,尤其是在搭建设备驱动框架这一块,为了提供一个通用的接口管理成千上万种设备,内核用C的面向对象思想,通过继承和多态,构建了一个复杂的系统,建议你好好看看内核代码,就会深刻体会到这一点

热心网友 时间:2022-04-13 05:30

看看这个例子吧

#include <stdio.h>

#ifndef C_Class
#define C_Class struct
#endif

C_Class A
{
C_Class A *A_this;
void (*Foo)(C_Class A *A_this);
int a;
int b;
};

C_Class B
{ //B继承了A
C_Class B *B_this; //顺序很重要
void (*Foo)(C_Class B *Bthis); //虚函数
int a;
int b;
int c;
};

void B_F2(C_Class B *Bthis)
{
printf("It is B_Fun\n");
}

void A_Foo(C_Class A *Athis)
{
printf("It is A.a=%d\n",Athis->a);//或者这里
// exit(1);
// printf("纯虚 不允许执行\n");//或者这里
}

void B_Foo(C_Class B *Bthis)
{
printf("It is B.c=%d\n",Bthis->c);
}

void A_Creat(struct A* p)
{
p->Foo=A_Foo;
p->a=1;
p->b=2;
p->A_this=p;
}

void B_Creat(struct B* p)
{
p->Foo=B_Foo;
p->a=11;
p->b=12;
p->c=13;
p->B_this=p;
}

int main(int argc, char* argv[])
{
C_Class A *ma,a;
C_Class B *mb,b;

A_Creat(&a);//实例化
B_Creat(&b);
mb=&b;
ma=&a;
ma=(C_Class A*)mb;//引入多态指针
printf("%d\n",ma->a);//可惜的就是 函数变量没有private
ma->Foo(ma);//多态
a.Foo(&a);//不是多态了
B_F2(&b);//成员函数,因为效率问题不使用函数指针
getchar();
return 0;
}

热心网友 时间:2022-04-13 07:54

用结构体就可以实现面向对象的方法。

热心网友 时间:2022-04-13 10:36

这问题很好.
事实上,C完全可以实现面向对象.
推荐你看<<面向对象的C编程>>这本书

热心网友 时间:2022-04-13 13:34

这么高深
没搞错吧,C语言是面向过程的!
原题发来

热心网友 时间:2022-04-13 16:48

网页链接

热心网友 时间:2022-04-13 20:20

用结构体
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
咖喱鸡块怎样烧好吃 小米摄像头安全吗会被别人看到吗 小米摄像头会被别人入侵吗 广联达计价软件gbq4.0中怎么显示小数位数 脸干怎么补水最有效 脸干补水最好土方法 为什么退契税 首套购房契税为什么退回 契税为什么会退 退购房契税什么意思 为什么买了房子要退契税 C语言如何实现 每次来月经量特别少,怎么办 青海盐湖海纳化工有限公司是盐湖集团控股的,还是... 月经紊乱,经量稀少怎么办 盐湖股份是不是可以买了 c语言如何 实现 c++中引用&的功能? 月经量少是怎么办 盐湖股份因为什么原因上涨 月经量很少,怎么办 月经量少而且不规律该怎么办啊? 月经量少怎么回事? 月经不调,月经量少,怎么调理 为什么tiktok上搜不到自己的店铺 FIGANB汽车功放什么牌子 改签火车票的规则时间 月经不调月经量少该怎么调理呢? 火车票可以改签异地吗 月经不规律,量少,怎么办? 有时候会需要改签火车票,那么有什么规则呢? 月经不调,量少怎么调理? 月经量少如何调理? c语言的实现 培养孩子的责任感,家长和老师都应该怎么做? 培养孩子的责任感的重要性 如何在用C语言实现输出“hello world“ 如何培养孩子的责任担当 格尔木钾肥厂分厂有哪些,有没有平泽钾肥厂?具体地... 用c语言实现下列要求 安赫莱斯盐湖海拔 C语言程序实现 想要从小培养孩子的责任感,应该从哪些方面开始抓起? 用c语言实现 如何用c语言实现多态 用c语言如何实现这个功能? 对“民权主义”理解正确的是() 在C语言中如何实现按任意键继续? 你知道孩子缺乏责任感的原因是什么吗 对三民主义中民权主义理解正确的是。 怎么用c语言实现选择界面 孩子缺乏责任心应该怎么办?家长应该如何教育?