00. 目錄
01. 概述
在C語言中還可以實現更深入的面向對象編程多態特性。例如:使用接口(interface)包含多個指向函數的指針,這樣就可以實現操作的"多態性"。
在面嚮對象語言C++的實現上,使用了虛函數的方式,虛函數實質上也是指向虛表(virtual table)的一個函數指針。C++虛表方式的本質和包含的各個函數指針的操作數據結構類似。
02. C語言基於對象編程實現部分多態功能
test.h文件內容如下:
#ifndef __TEST_H__
#define __TEST_H__
#ifdef __cplusplus
//表示是C語言的頭文件
extern "C"
{
#endif
typedef void * HPERSON;
//創建對象
HPERSON createPerson(const char *name);
//顯示對象
void displayPerson(HPERSON person);
//刪除對象
void deletePerson(HPERSON person);
//-----------------STUDENT-----------------
typedef void* HSTUDENT;
//創建對象
HSTUDENT createStudent(const char *name, int age, int id, int score);
//刪除對象
void deleteStudent(HSTUDENT student);
#ifdef __cplusplus
}
#endif
#endif /*__TEST_H__*/
test.c具體實現如下:
#define _CRT_SECURE_NO_WARNINGS
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//函數指針
typedef struct _PersonOps
{
void (*display)(HPERSON);
}PersonOps;
//Person表示HPERSON句柄指向的結構體
typedef struct _Person
{
//使用指針
char *name;
int age;
int id;
PersonOps* ops;
}Person;
//顯示對象
static void do_displayPerson(HPERSON person)
{
Person* p = person;
if (NULL == p)
{
printf("displayPerson 參數非法\n");
return;
}
printf("Name: %s age: %d id:%d\n", p->name, p->age, p->id);
}
static PersonOps opsPerson = {
do_displayPerson
};
//創建對象
HPERSON createPerson(const char * name)
{
Person *p = NULL;
printf("創建對象\n");
p = malloc(sizeof(Person));
if (NULL == p)
{
printf("分配內存失敗\n");
return NULL;
}
memset(p, 0, sizeof(Person));
p->name = malloc(strlen(name) + 1);
if (NULL == p->name)
{
printf("分配內存失敗\n");
return NULL;
}
strcpy(p->name, name);
p->age = 0;
p->id = 0;
p->ops = &opsPerson;
return p;
}
//顯示對象
void displayPerson(HPERSON person)
{
Person* p = person;
p->ops->display(person);
}
//刪除對象
void deletePerson(HPERSON person)
{
Person *p = person;
if (NULL == person)
{
return;
}
if (NULL != p->name)
{
free(p->name);
}
free(person);
}
//---------------------STUDENT--------------------
typedef struct _stu_t {
Person person;
int score;
}Student;
static void do_displayStudent(HSTUDENT student)
{
Student* s = student;
if (NULL == student)
{
return;
}
do_displayPerson(&(s->person));
printf("score: %d\n", s->score);
}
static PersonOps opsStudent = {
do_displayStudent
};
//創建對象
HSTUDENT createStudent(const char* name, int age, int id, int score)
{
Student *s = malloc(sizeof(Student));
if (NULL == s)
{
return NULL;
}
memset(s, 0, sizeof(Student));
s->person.name = malloc(strlen(name) + 1);
if (NULL == s->person.name)
{
return;
}
memset(s->person.name, 0, strlen(name) + 1);
strcpy(s->person.name, name);
s->person.age = age;
s->person.id = id;
s->score = score;
s->person.ops = &opsStudent;
return s;
}
//刪除對象
void deleteStudent(HSTUDENT student)
{
Student *s = student;
if (NULL == s)
{
return;
}
if (NULL != s->person.name)
{
free(s->person.name);
}
free(s);
}
main.c實現如下:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "test.h"
//主函數
int main()
{
HSTUDENT s = createStudent("李明", 12, 1, 99);
displayPerson(s);
deleteStudent(s);
system("pause");
return 0;
}
測試結果如下:
Name: 李明 age: 12 id:1
score: 99
請按任意鍵繼續. . .
03. 總結
在本例中,含有不同操作的結構體內存格式如下所示
PersonOpt數據結構是一個表示"對象"操作的函數表。該程序中它包含了一個操作函數(函數指針)display。在實際應用中,這種函數表數據結構還可能包含更多的數據結構。
總之,利用操作的函數指針列表可以實現部分“多態”功能,其本質是對於不同類型的數據結構調用不同的實現函數。
04. 下載
4.1 代碼下載:C語言實現對象編程之多態代碼.rar