473,434 Members | 1,820 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,434 software developers and data experts.

run-time polymorphism in C (long)

The following example shows how an Object Oriented C programmer
might implement run-time polymorphism.
The Circle "class" is "derived" from the Shape "class".
Pointers to functions
which actually draw and compute the area of a shape
are stored in a "virtual function table"
and a pointer to the appropriate virtual function table
is stored in every shape object.
The "virtual" functions use this pointer to retrieve
a pointer to the "actual" function and call it
through this pointer.

$ cat Point.h
#ifndef Guard_Point_h
#define Guard_Point_h 1

typedef struct Point {
/* representation */
double X;
double Y;
} Point;
/* functions */
double
xPoint(const Point* pP);
double
yPoint(const Point* pP);
/* constructors */
Point
createDefaultPoint(void);
Point
createExplicitPoint(double x, double y);
/* destructor */
void
destroyPoint(const Point* pP);

#endif/* Guard_Point_h */

$ cat Point.c
/* gcc -I. -O2 -c Point.c
*/
#include<Point.h>

/* functions */
double
xPoint(const Point* pP) {
return pP->X; }
double
yPoint(const Point* pP) {
return pP->Y; }
/* constructors */
Point
createDefaultPoint(void) {
Point p;
p.X = 0.0;
p.Y = 0.0;
return p; }
Point
createExplicitPoint(double x, double y) {
Point p;
p.X = x;
p.Y = y;
return p;
}
/* destructor */
void
destroyPoint(const Point* pP) { }

$ cat Color.h
#ifndef Guard_Color_h
#define Guard_Color_h 1
typedef struct Color {
unsigned char R; /* red */
unsigned char G; /* green */
unsigned char B; /* blue */
} Color;
/* functions */
unsigned int
redColor(const Color* pC);
unsigned int
greenColor(const Color* pC);
unsigned int
blueColor(const Color* pC);
/* constructors */
Color
createDefaultColor(void);
Color
createExplicitColor(
unsigned int r,
unsigned int g,
unsigned int b);
/* destructor */
void
destroyColor(const Color* pC);

#endif/* Guard_Color_h */

$ cat Color.c
/* gcc -I. -O2 -c Color.c
*/
#include<Color.h>

/* functions */
unsigned int
redColor(const Color* pC) {
return pC->R; }
unsigned int
greenColor(const Color* pC) {
return pC->G; }
unsigned int
blueColor(const Color* pC) {
return pC->B; }
/* constructors */
Color
createDefaultColor(void) {
Color c;
c.R = 0;
c.G = 0;
c.B = 0;
return c; }
Color
createExplicitColor(
unsigned int r,
unsigned int g,
unsigned int b) {
Color c;
c.R = r;
c.G = g;
c.B = b;
return c; }
/* destructor */
void
destroyColor(const Color* pC) { }

$ cat Shape.h
#ifndef Guard_Shape_h
#define Guard_Shape_h 1

#include<Point.h>
#include<Color.h>

typedef struct Shape {
const
void* pV; /* virtual function table */
Point P; /* first public base class */
Color C; /* second public base class */
} Shape;
/* functions */
Point*
pointShape(Shape* pS);
Color*
colorShape(Shape* pS);
void
drawShape(const Shape* pS);
void
actualDrawShape(const Shape* pS);
double
areaShape(const Shape* pS);
double
actualAreaShape(const Shape* pS);
/* constructors */
Shape
createDefaultShape(void);
Shape
createExplicitShape(
const Point* pP,
const Color* pC);
/* destructor */
void
destroyShape(const Shape* pS);

#endif/* Guard_Shape_h */

$ cat Shape.c
/* gcc -I. -O2 -c Shape.c
*/
#include<stdio.h>
#include<Shape.h>

/* functions */
Point*
pointShape(Shape* pS) {
return &(pS->P); }
Color*
colorShape(Shape* pS) {
return &(pS->C); }
void
actualDrawShape(const Shape* pS) {
fprintf(stderr, "drawShape(const Shape*)\n");
fflush(stderr); }
double
actualAreaShape(const Shape* pS) {
fprintf(stderr, "areaShape(const Shape*)\n");
fflush(stderr);
return 0.0; }

typedef struct vTableShape_t {
void (*drawShape)(const Shape*);
double (*areaShape)(const Shape*);
} vTableShape_t;
static const vTableShape_t
vTableShape = {actualDrawShape, actualAreaShape};
void
drawShape(const Shape* pS) {
((vTableShape_t*)(pS->pV))->drawShape(pS); }
double
areaShape(const Shape* pS) {
return ((vTableShape_t*)(pS->pV))->areaShape(pS); }
/* initializers */
Shape* initializeDefaultShape(Shape* pS, const void* pV) {
pS->pV = pV;
pS->P = createDefaultPoint();
pS->C = createDefaultColor();
return pS; }
Shape* initializeExplicitShape(Shape* pS, const void* pV,
const Point* pP, const Color* pC) {
pS->pV = pV;
pS->P = *pP;
pS->C = *pC;
return pS; }
/* constructors */
Shape
createDefaultShape(void) {
Shape S;
initializeDefaultShape(&S, &vTableShape);
return S; }
Shape
createExplicitShape(
const Point* pP,
const Color* pC) {
Shape S;
return *initializeExplicitShape(&S, &vTableShape, pP, pC); }
/* destructor */
void
destroyShape(const Shape* pS) {
destroyColor(colorShape((Shape*)pS));
destroyPoint(pointShape((Shape*)pS)); }

$ cat Circle.h
#ifndef Guard_Circle_h
#define Guard_Circle_h 1

#include<Shape.h>

typedef struct {
Shape S; /* public base class */
double R; /* radius */
} Circle;
/* functions */
Shape*
shapeCircle(Circle* pC);
double
radiusCircle(const Circle* pC);
void
drawCircle(const Circle* pC);
void
actualDrawCircle(const Circle* pC);
double
areaCircle(const Circle* pC);
double
actualAreaCircle(const Circle* pC);
/* constructors */
Circle
createDefaultCircle(void);
Circle
createExplicitCircle(const Point* pP,
const Color* pC, double r);
/* destructor */
void
destroyCircle(const Circle* pC);

#endif/* Guard_Circle_h */

$ cat Circle.c
/* gcc -I. -O2 -c Circle.c
*/
#include<math.h>
#include<stdio.h>
#include<Circle.h>

/* functions */
Shape*
shapeCircle(Circle* pC) {
return &(pC->S); }
double
radiusCircle(const Circle* pC) {
return pC->R; }
void
actualDrawCircle(const Circle* pC) {
fprintf(stderr, "actualDrawCircle(const Circle*)\n");
fflush(stderr); }
double
actualAreaCircle(const Circle* pC) {
const
double pi = 3.14159265358979323846;
double r = radiusCircle(pC);
fprintf(stderr, "actualAreaCircle(const Circle*)\n");
fflush(stderr);
return pi*r*r; }

typedef struct vTableCircle_t {
void (*drawCircle)(const Circle*);
double (*areaCircle)(const Circle*);
} vTableCircle_t;
static const vTableCircle_t
vTableCircle = {actualDrawCircle, actualAreaCircle};
void
drawCircle(const Circle* pC) {
((vTableCircle_t*)(pC->S.pV))->drawCircle(pC); }
double
areaCircle(const Circle* pC) {
return ((vTableCircle_t*)(pC->S.pV))->areaCircle(pC); }
/* constructors */
Circle
createDefaultCircle(void) {
Circle C;
extern Shape* initializeDefaultShape(Shape*, const void*);
initializeDefaultShape(&(C.S), &vTableCircle);
C.R = 0.0;
return C; }
Circle
createExplicitCircle(const Point* pP,
const Color* pC, double r) {
Circle C;
extern Shape* initializeExplicitShape(Shape*, const void*,
const Point*, const Color*);
initializeExplicitShape(&(C.S), &vTableCircle, pP, pC);
C.R = r;
return C; }
/* destructor */
void
destroyCircle(const Circle* pC) {
destroyShape(shapeCircle((Circle*)pC)); }

$ cat main.c
/* gcc -I. -O2 -o main main.c Circle.o Shape.o Color.o Point.o
*/
#include<stdio.h>
#include<Circle.h>

int
main(int argc, char* argv[]) {
const Point point = createDefaultPoint();
const Color color = createDefaultColor();
const Circle circle = createExplicitCircle(
&point, &color, 2.0);
drawShape((Shape*)(&circle));
fprintf(stdout, "%g = radius\t %g = area\n",
radiusCircle(&circle), areaShape((Shape*)(&circle)));
destroyCircle(&circle);
destroyColor(&color);
destroyPoint(&point);
return 0;
}

Nov 14 '05 #1
6 1513
E. Robert Tisdale wrote:
The following example shows how an Object Oriented C programmer
might implement run-time polymorphism.
The Circle "class" is "derived" from the Shape "class".
Pointers to functions
which actually draw and compute the area of a shape
are stored in a "virtual function table"
and a pointer to the appropriate virtual function table
is stored in every shape object.
The "virtual" functions use this pointer to retrieve
a pointer to the "actual" function and call it
through this pointer.

....snip...

Seems interesting. But, could you please indent the code
'properly' and please use vertical white space. This code
hurts my eyes and is very frustrating because the common
visual clues are missing: It is unclear where definitions
and/or function calls begin and/or end. Have a look at K&R
for a 'good' example of 'proper' indentation. (At least
place } at a line of there own, I would say.)

Kees

Nov 14 '05 #2
in comp.lang.c i read:
Pointers to functions which actually draw and compute the area of a shape
are stored in a "virtual function table" and a pointer to the appropriate
virtual function table is stored in every shape object. const
void* pV; /* virtual function table */


standard c does not require an implementation to meaningfully handle
conversion between a function pointer and an object pointer.

--
a signature
Nov 14 '05 #3
Something that calls itself
those who know me have no need of my name wrote:


Pointers to functions which actually draw and compute the area of a shape
are stored in a "virtual function table" and a pointer to the appropriate
virtual function table is stored in every shape object.


const
void* pV; /* virtual function table */

standard c does not require an implementation to meaningfully handle
conversion between a function pointer and an object pointer.


What would you suggest instead?

Nov 14 '05 #4
In article <m1*************@usa.net>
those who know me have no need of my name <no****************@usa.net> wrote:
in comp.lang.c i read:
Pointers to functions which actually draw and compute the area of a shape
are stored in a "virtual function table" and a pointer to the appropriate
virtual function table is stored in every shape object.
const
void* pV; /* virtual function table */


standard c does not require an implementation to meaningfully handle
conversion between a function pointer and an object pointer.


In general, vtables are data objects, and the description (quoted
in ">>" above) sounds as though this is the case here. The
"void *" in pV would presumably point to the data object, which
in turn has pointers to functions.

Of course, when one is "manually expanding" such things in C, there
is no reason not to use a pointer to the structure containing the
(named) operations:

struct zorg_ops {
void (*increase_evilness)(struct zorg *, double howmuch);
void (*absorb_missles)(struct zorg *, int nmissiles);
/* ... */
};

struct zorg {
/* any base class goes here */
struct zorg_ops *ops;
double degree_of_evil;
/* ... more data members as needed */
};

Then when one has a "struct zorg *" and wants it to absorb three
missiles:

struct zorg *zp;
...
zp->ops->absorb_missiles(zp, 3);

In the usual case, the "ops" would actually be part of the base
class, so this:

zp->base.ops->absorb(zp, 3);

might be a bit more likely.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #5
in comp.lang.c i read:
Something that calls itself
those who know me have no need of my name wrote:

Pointers to functions [...] are stored in a "virtual function table"
standard c does not require an implementation to meaningfully handle
conversion between a function pointer and an object pointer.


What would you suggest instead?


i don't have a suggestion for you. i just wanted to point out that this
technique isn't highly portable.

--
a signature
Nov 14 '05 #6
Something that calls itself those who know me have no need of my name wrote:
in comp.lang.c i read:
Something that calls itself
those who know me have no need of my name wrote:


Pointers to functions [...] are stored in a "virtual function table"
standard c does not require an implementation to meaningfully handle
conversion between a function pointer and an object pointer.


What would you suggest instead?

i don't have a suggestion for you.
i just wanted to point out that this technique isn't highly portable.


You are confused. There is *no*
"conversion between a function pointer and an object pointer"
in my example.

Nov 14 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Ed | last post by:
Hello, I took a course in asp about 2 years ago and I was practicing with IIS 5.0. Then I put it down for a while. Now trying to get back to it. I can't run asp files from subdirectories of...
4
by: Primo | last post by:
Hi, This problem has been frustrating me for days and I hope you experts can help me out. I am trying to run a command, which I would normally run from the command line, from within my C#...
13
by: Bob Day | last post by:
Using vs2003, vb.net I start a thread, giving it a name before start. Code snippet: 'give each thread a unique name (for later identification) Trunk_Thread.Name = "Trunk_0_Thread" ' allow...
3
by: emman_54 | last post by:
Hi every one, I am trying to run a batch file using my asp.net application. I am using the Process class to run the batch file. When I run my web application, In the task manager, i could see...
19
by: Bryan | last post by:
How can i run a bit of code straight from the IDE? Right now i make a temporary button and put the code behind that, then i run debug mode and click on the button. Is there a way to highlight...
9
by: Brett Wesoloski | last post by:
I am new to VS2005. I changed my program.cs file to be a different form I am working on. But when I go to run the application it still brings up the form that was originally declared as new. ...
7
by: Lee Crabtree | last post by:
I remember when I was first getting into .NET Forms programming that there was a rather emphatic rule about not constructing a form before calling Application.Run with it. So this: ...
8
by: David Thielen | last post by:
Hi; In our setup program how do I determine if I need to run "aspnet_regiis –i" and if so, is there an API I can calll rather than finding that program on the user's disk and calling it? --...
3
by: traceable1 | last post by:
Is there a way I can set up a SQL script to run when the instance starts up? SQL Server 2005 SP2 thanks!
7
by: mxdevit | last post by:
Task: run application from ASP.NET for example, you have a button on ASP.NET page, when press this button - one application is invoked. the code to run application (for example, notepad) is...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.