这种问题比较锻炼思维,同时考察c和c++的掌握程度。如果你遇到过类似问题,此题意义自不必说。如果用c实现c++,主要解决如何实现封装,继承和多态三大问题,本文分两块说。

1、封装

// Example class A contains regular and
// static member variables and methods.class A
{
private:int m_x;static int g_y;int m_z;// Should be invoked when the object endsvoid InformEnd();public:A(int x);~A();void UpdateX(int newX);static void UpdateY(int newY);
};// Initialization of the static variable
int A::g_y = 0;// The non-static member variables
// are initialized in the constructor
A::A(int x)
{m_x = x;m_z = 0;
}// Destructor invokes a private variable
A::~A()
{InformEnd();
}// UpdateX checks the value of X against  a static variable before updating the value
void A::UpdateX(int newX)
{if (g_y != 0 && m_x < newX){m_x = newX;}
}// Unconditional update of static variable m_y
void A::UpdateY(int newY)
{g_y = newY;
}main()
{// Create a object on the heapA *pA = new A(5);// Create an object on the stackA a(6);// Example of an access via a pointerpA->UpdateX(8);// Example of a direct accessa.UpdateX(9);// Example of static method callA::UpdateY(1000);// Deleting the object
    delete pA;
}
/*
This code maps from the C++ code to the equivalent C code.
Mapping of the following entities is covered:
- classes                 - methods
- this pointer            - member variables
- constructors            - static methods
- destructors             - static variables
*/#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int BOOLEAN;/*
Structure A represents the class A. Only the non-static member
variables are present in the structure
*/
struct A
{int m_x;int m_z;
};/* Notice that g_y is not a part of struct A. Its a separate global variable. */
int g_y = 0;/*
Prototype for the InformEnd method. The C++ version of this method
did not have any parameters but the C mapped function needs the this
pointer to obtain the address of the object. Note that all non-static
methods in the C++ code would map to a C function the additional this
pointer as the first parameter.
*/
void InformEnd(A *this_ptr);/*
The constructor maps to function with the this pointer and the size of the
structure as parameters. this_ptr passed to the constructor is NULL when
the operator new is used to create the object. this_ptr contains a valid
pointer if the memory for the object to be constructed is already
allocated. (e.g. local variable or part of another structure.)
*/
A *A_Constructor(A *this_ptr, int x)
{/*Check if memory has been allocated for struct A. */if (this_ptr == NULL){/*Allocate memory of size A. */this_ptr = (A *) malloc(sizeof(A));}/* Once the memory has been allocated for A, initialise members of A. */if (this_ptr){this_ptr->m_x = x;this_ptr->m_z = 0;}return this_ptr;
}/*
The following function is equivalent to a destructor. The this
pointer and a dynamic flag are passed as the two parameters to
this function. The dynamic flag is set to true if the object is
being deleted using the delete operator.
*/
void A_Destructor(A *this_ptr, BOOLEAN dynamic)
{InformEnd(this_ptr);/* If the memory was dynamically allocated for A, explicitly free it. */if (dynamic){free(this_ptr);}
}/*
A pointer this is passed as first argument. All member variables
in the code will be accessed through an indirecion from the this
pointer. Notice that static variables are accessed directly as
they do not belong to any instance.
*/
void A_UpdateX(A *this_ptr, int newX)
{if (g_y != 0 && this_ptr->m_x < newX){this_ptr->m_x = newX;}
}/*
Notice that this is not passed here. This is so because
A_UpdateY is a static function. This function can only access
other static functions and static or global variables. This
function cannot access any member variables or methods of class A
as a static function does not correspond to an instance.
*/
void A_UpdateY(int newY)
{g_y = newY;
}main()
{/*Dynamically allocate memory by passing NULL in this arguement.Also initialize members of struct pointed to by pA.*/A *pA = A_Constructor(NULL, 5);/* Define local variable a of type struct A. */A a;/*Initialize members of struct variable a. Note that theconstructor is called with the address of the object asa has been pre-allocated on the stack.*/A_Constructor(&a, 6);/*Method invocations in C++ are handled by calling thecorresponding C functions with the object pointer.*/A_UpdateX(pA, 8);A_UpdateX(&a, 9);/* UpdateY is a static method, so object pointer is not passed */A_UpdateY(1000);/*Delete memory pointed to by pA (explicit delete inoriginal code).*/A_Destructor(pA, TRUE);/*Since memory was allocated on the stack for local struct variable a, it will be deallocated when a goes out of scope.The destructor will also be invoked. Notice that dynamic flagis set to false so that the destructor does not try tofree memory.*/A_Destructor(&a, FALSE);
}

2、继承/多态

// A typical example of inheritance and virtual function use.
// We would be mapping this code to equivalent C.// Prototype graphics library function to draw a circle
void glib_draw_circle (int x, int y, int radius);// Shape base class declaration
class Shape
{
protected:int m_x;    // X coordinateint m_y;  // Y coordinatepublic:// Pure virtual function for drawingvirtual void Draw() = 0; // A regular virtual functionvirtual void MoveTo(int newX, int newY);// Regular method, not overridable.void Erase();// Constructor for ShapeShape(int x, int y);// Virtual destructor for Shapevirtual ~Shape();
};// Circle class declaration
class Circle : public Shape
{
private:int m_radius;    // Radius of the circlepublic:// Override to draw a circlevirtual void Draw();   // Constructor for CircleCircle(int x, int y, int radius);// Destructor for Circlevirtual ~Circle();
};// Shape constructor implementation
Shape::Shape(int x, int y)
{m_x = x;m_y = y;
}// Shape destructor implementation
Shape::~Shape()
{
//...
}// Circle constructor implementation
Circle::Circle(int x, int y, int radius) : Shape (x, y)
{m_radius = radius;
}// Circle destructor implementation
Circle::~Circle()
{
//...
}// Circle override of the pure virtual Draw method.
void Circle::Draw()
{glib_draw_circle(m_x, m_y, m_radius);
}main()
{// Define a circle with a center at (50,100) and a radius of 25Shape *pShape = new Circle(50, 100, 25);// Define a circle with a center at (5,5) and a radius of 2Circle aCircle(5,5, 2);// Various operations on a Circle via a Shape pointerpShape->Draw();pShape->MoveTo(100, 100);pShape->Erase();delete pShape;// Invoking the Draw method directly
  aCircle.Draw();
}/*
C code
The following code maps the C++ code for the Shape and Circle classes
to C code.
*/#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int BOOLEAN;/*
Error handler used to stuff dummy VTable
entries. This is covered later.
*/
void pure_virtual_called_error_handler();/* Prototype graphics library function to draw a circle */
void glib_draw_circle (int x, int y, int radius);typedef void (*VirtualFunctionPointer)(...);/*
VTable structure used by the compiler to keep
track of the virtual functions associated with a class.
There is one instance of a VTable for every class
containing virtual functions. All instances of
a given class point to the same VTable.
*/
struct VTable
{/*d and i fields are used when multiple inheritance and virtualbase classes are involved. We will be ignoring them for thisdiscussion.*/int d;int i;/*A function pointer to the virtual function to be called isstored here.*/VirtualFunctionPointer pFunc;
};/*
The Shape class maps into the Shape structure in C. All
the member variables present in the class are included
as structure elements. Since Shape contains a virtual
function, a pointer to the VTable has also been added.
*/struct Shape
{int m_x;int m_y;/*The C++ compiler inserts an extra pointer to a vtable whichwill keep a function pointer to the virtual function thatshould be called.*/VTable *pVTable;
};/*
Function prototypes that correspond to the C++ methods
for the Shape class,
*/
Shape *Shape_Constructor(Shape *this_ptr, int x, int y);
void Shape_Destructor(Shape *this_ptr, bool dynamic);
void Shape_MoveTo(Shape *this_ptr, int newX, int newY);
void Shape_Erase(Shape *this_ptr);/*
The Shape vtable array contains entries for Draw and MoveTo
virtual functions. Notice that there is no entry for Erase,
as it is not virtual. Also, the first two fields for every
vtable entry are zero, these fields might have non zero
values with multiple inheritance, virtual base classes
A third entry has also been defined for the virtual destructor
*/VTable VTableArrayForShape[] =
{/*Vtable entry virtual function Draw.Since Draw is pure virtual, this entryshould never be invoked, so call error handler*/{ 0, 0, (VirtualFunctionPointer) pure_virtual_called_error_handler },/*This vtable entry invokes the base class'sMoveTo method.*/{ 0, 0, (VirtualFunctionPointer) Shape_MoveTo },/* Entry for the virtual destructor */{ 0, 0, (VirtualFunctionPointer) Shape_Destructor }
};/*
The struct Circle maps to the Circle class in the C++ code.
The layout of the structure is:
- Member variables inherited from the the base class Shape.
- Vtable pointer for the class.
- Member variables added by the inheriting class Circle.
*/struct Circle
{/* Fields inherited from Shape */int m_x;int m_y;VTable *pVTable;/* Fields added by Circle */int m_radius;
};/*
Function prototypes for methods in the Circle class.
*/Circle *Circle_Constructor(Circle *this_ptr, int x, int y, int radius);
void Circle_Draw(Circle *this_ptr);
void Circle_Destructor(Circle *this_ptr, BOOLEAN dynamic);/* Vtable array for Circle */VTable VTableArrayForCircle[] =
{/*Vtable entry virtual function Draw.Circle_Draw method will be invoked when Shape'sDraw method is invoked*/{ 0, 0, (VirtualFunctionPointer) Circle_Draw },/*This vtable entry invokes the base class'sMoveTo method.*/{ 0, 0, (VirtualFunctionPointer) Shape_MoveTo },/* Entry for the virtual destructor */{ 0, 0, (VirtualFunctionPointer) Circle_Destructor }
};Shape *Shape_Constructor(Shape *this_ptr, int x, int y)
{/* Check if memory has been allocated for struct Shape. */if (this_ptr == NULL){/* Allocate memory of size Shape. */this_ptr = (Shape *) malloc(sizeof(Shape));}/*Once the memory has been allocated for Shape,initialise members of Shape.*/if (this_ptr){  /* Initialize the VTable pointer to point to shape */this_ptr->pVTable = VTableArrayForShape;this_ptr->m_x = x;this_ptr->m_y = y;}return this_ptr;
}void Shape_Destructor(Shape *this_ptr, BOOLEAN dynamic)
{/*Restore the VTable to that for Shape. This isrequired so that the destructor does not invokea virtual function defined by a inheriting class.(The base class destructor is invoked after inheritingclass actions have been completed. Thus it is notsafe to invoke the ineriting class methods from thebase class destructor)*/this_ptr->pVTable = VTableArrayForShape;/*...*//*If the memory was dynamically allocatedfor Shape, explicitly free it.*/if (dynamic){free(this_ptr);}
}Circle *Circle_Constructor(Circle *this_ptr, int x, int y, int radius)
{/* Check if memory has been allocated for struct Circle. */if (this_ptr == NULL){/* Allocate memory of size Circle. */this_ptr = (Circle *) malloc(sizeof(Circle));}/*Once the memory has been allocated for Circle,initialise members of Circle.*/if (this_ptr){/* Invoking the base class constructor */Shape_Constructor((Shape *)this_ptr, x, y);/* Noting that here pointer is to circle rather than shapeThis overwriting the pointer set to shape in shape's constructor */this_ptr->pVTable = VTableArrayForCircle;this_ptr->m_radius = radius;}return this_ptr;
}void Circle_Destructor(Circle *this_ptr, BOOLEAN dynamic)
{/* Restore the VTable to that for Circle */this_ptr->pVTable = VTableArrayForCircle;/*...*//*Invoke the base class destructor after ineriting classdestructor actions have been completed. Also note thatthat the dynamic flag is set to false so that the shapedestructor does not free any memory.*/Shape_Destructor((Shape *) this_ptr, FALSE);/*If the memory was dynamically allocatedfor Circle, explicitly free it.*/if (dynamic){free(this_ptr);}
}void Circle_Draw(Circle *this_ptr)
{glib_draw_circle(this_ptr->m_x, this_ptr->m_y, this_ptr->m_radius);
}main()
{   /*Dynamically allocate memory by passing NULL in this arguement.Also initialse members of struct pointed to by pShape.*/Shape *pShape = (Shape *) Circle_Constructor(NULL, 50, 100, 25);/* Define a local variable aCircle of type struct Circle. */Circle aCircle;/* Initialise members of struct variable aCircle. */Circle_Constructor(&aCircle, 5, 5, 2);/*Virtual function Draw is called for the shape pointer. The compilerhas allocated 0 offset array entry to the Draw virtual function.This code corresponds to "pShape->Draw();"*/(pShape->pVTable[0].pFunc)(pShape);/*Virtual function MoveTo is called for the shape pointer. The compilerhas allocared 1 offset array entry to the MoveTo virtual function.This code corresponds to "pShape->MoveTo(100, 100);"*/(pShape->pVTable[1].pFunc)(pShape, 100, 100);/*The following code represents the Erase method. This method isnot virtual and it is only defined in the base class. Thusthe Shape_Erase C function is called.*/Shape_Erase(pShape);/* Delete memory pointed to by pShape (explicit delete in original code).Since the destructor is declared virtual, the compiler has allocated2 offset entry to the virtual destructorThis code corresponds to "delete pShape;".*/(pShape->pVTable[2].pFunc)(pShape, TRUE);/*The following code corresponds to aCircle.Draw().Here the compiler can invoke the method directly instead ofgoing through the vtable, since the type of aCircle is fullyknown. (This is very much compiler dependent. Dumb compilers willstill invoke the method through the vtable).*/Circle_Draw(&aCircle);/*Since memory was allocated from the stack for local struct variable aCircle, it will be deallocated when aCircle goes out of scope.The destructor will also be invoked. Notice that dynamic flag is set tofalse so that the destructor does not try to free memory. Again, thecompiler does not need to go through the vtable to invoke the destructor.*/Circle_Destructor(&aCircle, FALSE);
}

参考链接:c实现原文 http://www.eventhelix.com/realtimemantra/Object_Oriented/

ooc原则:http://www.eventhelix.com/realtimemantra/Object_Oriented/#.UyRbuY3HkqL

参考书籍:Object-oriented programming with ANSI-C

转载于:https://www.cnblogs.com/zhaoyl/p/3602542.html

c语言实现面向对象OOC相关推荐

  1. C语言实现面向对象示例

    用C语言实现面向对象的方法,面向对象的三个基本特征,对象唯一性,继承性,抽象性. 使用C语言中的结构体和函数指针将数据与操作放在一起,使得一个问题的解决方法封装在结构体中. 其中结构体的嵌套使用实现了 ...

  2. C语言实现面向对象的思想

    用C语言实现面向对象的方法,面向对象的三个基本特征,对象唯一性,继承性,抽象性. 使用C语言中的结构体和函数指针将数据与操作放在一起,使得一个问题的解决方法封装在结构体中. 其中结构体的嵌套使用实现了 ...

  3. C++学习笔记:(七)C语言实现面向对象编程

    面试官:C和C++有什么不同? 应聘者:一个是面向过程,一个是面向对象. 这样的答案在我看是不完全正确,因为面向过程编程和面向对象编程是编程思想,C++可以用面向过程的思想编程,同样,C语言也可以用面 ...

  4. c语言中如何使用面向对象编程,如何使用C语言的面向对象

    我们都知道,C++才是面向对象的语言,但是C语言是否能使用面向对象的功能? (1)继承性 typedef struct _parent { int data_parent; }Parent; type ...

  5. 如何使用C语言的面向对象?

    我们都知道,C 才是面向对象的语言,但是C语言是否能使用面向对象的功能? (1)继承性 typedef struct _parent { int data_parent; }Parent; typed ...

  6. 数据结构与算法(C#版)第二章 C#语言与面向对象技术(下)V1.0

    由于本学期我给本科生上<数据结构与算法>这门课程,边上边把自己的教案进行总结,发到CSDN上面,希望大家多多指正. 第二章 C#语言与面向对象技术(下) 二.面向对象技术 5.属性 6.索 ...

  7. 数据结构与算法(C#版)第二章 C#语言与面向对象技术(中)V1.0

    由于本学期我给本科生上<数据结构与算法>这门课程,边上边把自己的教案进行总结,发到CSDN上面,希望大家多多指正. 第二章 C#语言与面向对象技术(中) 二.面向对象技术 1.类与对象 2 ...

  8. 数据结构与算法(C#版)第二章 C#语言与面向对象技术(上)V1.0

    由于本学期我给本科生上<数据结构与算法>这门课程,边上边把自己的教案进行总结,发到CSDN上面,希望大家多多指正. 第二章 C#语言与面向对象技术(上) 一.C#语言 1.数据类型 2.常 ...

  9. c语言uint32_使C语言实现面向对象的三个要素,你掌握了吗?

    编排 | strongerHuang 微信公众号 | strongerHuang 不知道有多少人去了解过语言的发展史,早期C语言的语法功能其实比较简单.随着应用需求和场景的变化,C语言的语法功能在不断 ...

  10. 飞鸽传书2007程序语言的面向对象最后会成自然语言吗?

    飞鸽传书2007程序语言的面向对象最后会成自然语言吗?程序语言的向自然语言靠拢,自底向上还是自顶向下? 飞鸽传书2007绿色版: http://www.freeeim.com/ipmsg/ipmsg_ ...

最新文章

  1. ArcGIS Javascript查询数据库并添加到地图上
  2. 计算机网络(一)计算机网络概述、组成、功能分类、性能指标 | 思维导图
  3. JavaScript数据结构和算法
  4. 图像白化MATLAB代码实现
  5. 对数学本质特征的若干认识
  6. matlab 中括号
  7. Debian/Ubuntu - 解决Root用户不能远程连接服务器的问题
  8. 根据shp文件创建Mask文件
  9. shell脚本小程序之特洛伊木马示例
  10. ZT华尔街日报:中国楼市泡沫的破灭预言 暴跌70%
  11. Java中Comparable比较器的基本用法
  12. R语言关联分析之啤酒和尿布
  13. vue文件夹上传组件选哪个好?
  14. 《操作系统》工作集详解
  15. 《SQL基础》04. SQL-DQL
  16. 【面试题】一个Http请求的流程
  17. 技术支持程序员程序书写规范
  18. leetcode java 大厂基础面试题附答案(二)
  19. [pyecharts学习笔记]——Pie饼图
  20. Python之路 34:并发与并行、锁(GIL、同步锁、死锁与递归锁)、信号量、线程队列、生消模型、进程(基础使用、进程通信、进程池、回调函数)、协程

热门文章

  1. VMware Guided Consolidation
  2. 一年级上册计算机教学计划,一年级信息技术上册教学计划
  3. 无法在linux下启用ttysac0串口 终端只打印信息,启动出现mmc0: error -110 whilst initialising SD card该如何解决?...
  4. 蓄水池采样算法的python实现_蓄水池采样算法-Reservoir Sampling
  5. Godot官网新闻翻译 - 2015年
  6. 第二届全国中学生网络安全竞赛线上 writeup
  7. 微信8.0.3:做重了群公告,再也不能@所有人了!
  8. 山东大学项目实训(三十二)—— 科室管理
  9. 无线路由当交换机的设置方法
  10. 微信测试之本地接口测试-ngrok