C面向对象之透明指针的运用

不透明指针(opaque pointer)可以用来在C中实现封装。

什么是不透明指针(opaque pointer)

从字面意思来看,“不透明”意味着看不到内部,因此“不透明指针”即看不到内部定义的指针。这样说有些抽象,我们来看个例子:

#include <stdio.h>
typedef void   *opque_data;
typedef struct AAA *opque_stru;

int main()
{
   opque_data data = 0;
   opque_stru stru = 0;
   printf("Hello, World! \n");
   
   return 0;
}

上面的程序可以build通过(也许你会觉得疑惑),data和stru 指针所指的type(AAA)细节是什么,我们不得而知。我们可以自由的操纵这种指针,但无法解引用,即无法查看指针所指向结构的内部信息,只有接口的实现才有这种特权。

透明指针面向对象应用

void *型指针作为一种通用的指针,可以和其它任何类型的指针(函数指针除外)相互转化而不需要类型强制转换,但不能对它进行解引用及下标操作。

在.h文件中声明不包含任何实现细节的结构体,在.c中定义与数据结构的特定实现函数。用一个链表的代码(来自《深入理解C指针》)来说明透明指针的用法。

下面链表的代码中,link并没有与具体的data绑定,而是关联一个void *Data.

link.h

#ifndef LINK_H
#define LINK_H

typedef void* Data;  /* opaque pointer */

typedef struct _linkedList LinkedList;
LinkedList* getLinkedListInstance();
void removeLinkedListInstance(LinkedList* list);
void addNode(LinkedList*, Data);
Data removeNode(LinkedList *);

#endif

link.c

#include "link.h"
#include <stdlib.h>

typedef struct _node{
    Data* data;   /*here use “Data data;” is also ok */
    struct _node* next;
} Node;

struct _linkedList{
    Node* head;
};

LinkedList* getLinkedListInstance(){
    LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
    list->head = NULL;

    return list;
}

void removeLinkedListInstance(LinkedList* list){
    Node *tmp = list->head;
    while(tmp != NULL){
        free(tmp->data); /* potential memeory leak, 
                            it denpeds on if any pointer inside real type of data */
        Node *current = tmp;
        tmp = tmp->next;
        free(current);
    }
    free(list);
}

void addNode(LinkedList* list, Data data){
    Node *node = (Node *)malloc(sizeof(Node));
    node->data = data;
    if(list->head == NULL){
        list->head = node;
        node->next = NULL;
    }else{
        node->next = list->head;
        list->head = node;
    }  
}

Data removeNode(LinkedList *list){
    if(list->head == NULL){
        return NULL;
    }else{
        Node* tmp = list->head;
        Data* data = tmp->data;
        list->head = list->head->next;
        free(tmp);   /* only free node, data is not free here */

        return data;  /* notes: data inside node returned, client need to free it,  */
    }
}

下面我们定义一个具体的node 数据类型Person.

person.h

#ifndef PERSON_H
#define PERSON_H

typedef struct _person{
    char* firstName;
    char* lastName;
    char* title;
    unsigned int age;
} Person;

void initPerson(Person *personPtr, const char* firstNamePtr, const char* lastNamePtr, const char* titlePtr, unsigned int age);
void delePerson(Person *personPtr);
void dispPerson(Person *personPtr);

#endif

person.c

#include "person.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void initPerson(Person *personPtr, 
                const char* firstNamePtr, 
                const char* lastNamePtr, 
                const char* titlePtr, 
                unsigned int age)
{
    personPtr->firstName = (char *)malloc(strlen(firstNamePtr) + 1);
    strcpy(personPtr->firstName, firstNamePtr);

    personPtr->lastName = (char *)malloc(strlen(lastNamePtr) + 1);
    strcpy(personPtr->lastName, lastNamePtr);

    personPtr->title = (char *)malloc(strlen(titlePtr) + 1);
    strcpy(personPtr->title, titlePtr);

    personPtr->age = age;
}

void delePerson(Person *personPtr)
{
    free(personPtr->firstName);
    free(personPtr->lastName);
    free(personPtr->title);
}

void dispPerson(Person *personPtr)
{
    printf("%s info name: %s %s\t title: %s\tage: %d\n", 
            personPtr->firstName, 
            personPtr->firstName, 
            personPtr->lastName, 
            personPtr->title, 
            personPtr->age);
}

main.c

#include "link.h"
#include "person.h"
#include <stdio.h>

int main(int argc, char **argv)
{
    LinkedList *list = getLinkedListInstance();
    Person *person = (Person *)malloc(sizeof(Person));
    initPerson(person, "Ricky", "ZEK", "Acmen", 36);
    addNode(list, person);
	
    person = (Person *)malloc(sizeof(Person));
    initPerson(person, "John", "OPP", "Develop", 28);
    addNode(list, person);
	
    person = (Person *)malloc(sizeof(Person));
    initPerson(person, "Ami", "VIV", "pet", 2);
    addNode(list, person);

	person = removeNode(list);
    dispPerson(person);
	delePerson(person);
	free(person);
	
    person = removeNode(list);
    dispPerson(person);
	delePerson(person);
	free(person);
	
	removeLinkedListInstance(list); /*memory leak, you can think of it */
	
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值