【C語言】C語言實現面向對象編程之多態

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

05. 附錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章