C/C++通用面向对象接口

来源:互联网 发布:网络投票怎么刷票软件 编辑:程序博客网 时间:2024/05/16 07:13

一,序
1,接口怎么做 自己在学习C/C++时的体会,如本文所述

2,什么是接口 实现一个功能的一组函数(或 方法)。

3,完美接口 与平台无关,与操作系统无关,甚至与语言无关;其他(例如:较少的接口函数,实现接口功能)略。

4,本文没有详尽的讲例子源码中(尤其是接口)每一个符号的含义,但实际上几乎每个符号都是有用意的。

5,如果C++部分,推荐两本书依次 <<C++ Primer>>、<<Inside C++ Object Model>>

6,本人以为,面向对象,只是一种效果;这种效果,C语言应该可以实现这个效果,不过可能会麻烦一点。

 

二,一般的 C 接口(面向对象的味道)
1,概述 得益于学习OpenSSL http://www.openssl.org;本文所讲的这种C语言接口还是比较基础,高手可以跳过;本人觉得这是种比较实用的接口方案。

2,接口原则 结构体打包接口使用到的所有数据;一般的,结构体指针作为接口函数第一个参数。

3,对外句柄 给调用者的可以不是结构体指针,可以是void*,这样可以把好多东西都做得透明。

4,借口扩展 新添接口函数就可以了。

5,比较经典的例子:zlib (http://www.zlib.net)。这是一个压缩的实现;压缩应该跟输入、输出无关;模式应该是"FilterInput"和"FilterOutput";z_stream数据结构,保存了所有和压缩有关的数据;所有"deflate"开头的接口函数,通过使用z_stream,实现了压缩功能;所有"inflate"开头接口函数,通过使用z_stream,实现了解压缩功能。

 

三,一般的 C++ 接口
1,原则 基类作接口,基类拥有所有接口方法,并且是虚的(virtual)。

2,原则 纯虚"空"基类。只有纯虚函数,没有构造函数,没有析构函数,没有数据成员。

3,实现 从接口基类派生,公有(public),非虚(non virtual);可多继承。

4,记得 额外多一个方法,用来摧毁对象;接口里面 “delete this;”就可以了。

5,调用 一定记得使用对象的 指针 或者 引用 调用。

6,接口扩展 从已有接口基类派生,公有(public),非虚(non virtual);增加新方法;单一继承,切记。

7,例子 微软COM,推荐:《Com本质论》;原理是C++的,并非微软的。

 

四,C / C++ 通用接口
 1,虚函数表地址 C++对象可以这个东西的。就在这里做文章,就在这里,就在这里。

 

C++ 接口
1,虚函数表地址 接口基类,有且仅有这个东西。也就是说,没有数据成员,仅有纯虚方法,没有构造、析构方法。

2,有自我摧毁接口(例如:Destroy)

 

C++ 实现
1,从 接口基类 公有派生,实现所有方法,可以有数据成员。

2,自我摧毁接口 只是简单的执行“delete this”,具有虚析构函数。

 

C 接口
1,制作虚函数表 struct,依序包含函数指针,一一对应虚函数;每个函数参数增加一对象的指针作为参数第一项。

2,制作对象 struct,仅包含虚函数表地址

4,推荐 宏定义一下每一个操作。

 

C实现
1, 实现函数使用static修饰,避免冲突。

2,使用接口定义的虚函数表 不必重新定义类型,推荐定义这个结构体变量,给定初值。

3,具体对象结构体 函数表指针务必放在第一个位置,之后放数据成员。

 

另外
2,特殊的创建 C++不能用new了,因为new C不支持,自己写一个方法。

 

五,例子 (MIDemo)
C实现Tiger

C++实现Bear

C接口调用 TIger、Bear

C++接口调用 Tiger、Bear

 Tiger用的是C,需要C版Animal接口;Bear用的是C++,需要C++版Animal接口;比较好的另一种解决办法是,各自做一个动态库,导出标准C函数符号。

MIC动态库:Tiger.c Animal.h Object.h mic.h mic.def

MICPP动态库:Bear.cpp  Animal.hpp Bear.hpp Object.hpp MICPP.hpp MICPP.def

 

C接口
/* Object.h */

#ifndef __Object_h__
#define __Object_h__


typedef struct ObjectVFT_st ObjectVFT;

typedef struct Object_st Object;


struct ObjectVFT_st
{
    void (* Destroy)(Object * This);
};

struct Object_st
{
    ObjectVFT * pvft;
};


#define Object_Destroy(This) (This)->pvft->Destroy(This)


#endif

 

/* Animal.h */

#ifndef __Animal_h__
#define __Animal_h__


#include "Object.h"


typedef struct Animal_st Animal;

typedef struct AnimalVFT_st AnimalVFT;

struct AnimalVFT_st
{
    void (* Destroy)(Animal * This);
    void (* SayHello)(Animal * This, int n);
    void (* SayHungry)(Animal * This, char * food);
};

struct Animal_st
{
    AnimalVFT * pvft;
};


#define Animal_Destroy(This) Object_Destroy(This)
#define Animal_SayHello(This, n) (This)->pvft->SayHello(This, n)
#define Animal_SayHungry(This, food) (This)->pvft->SayHungry(This, food)


#endif

 

C++接口
/* Object.hpp */

#ifndef __Object_hpp__
#define __Object_hpp__


class Object
{
public:
    virtual void Destroy(void) = 0;
};


#endif
 

/* Animal.hpp */

#ifndef __Animal_hpp__
#define __Animal_hpp__


#include "Object.hpp"


class Animal : public Object
{
public:
    virtual void SayHello(int n) = 0;
    virtual void SayHungry(char * food) = 0;

};


#endif
 

Tiger
 /* Tiger.c */

#include <stdlib.h>
#include <stdio.h>

#include "Tiger.h"
#include "MIC.h"


static void _Destory(Animal * This);
static void _SayHello(Animal * This, int n);
static void _SayHungry(Animal * This, char * food);


static AnimalVFT g_TigerVFT = {_Destory, _SayHello, _SayHungry};


typedef struct Tiger_st
{
    AnimalVFT * pvft;
    int age;
    char name[64];
}Tiger;

Animal * Tiger_new(void)
{
    Tiger * pTiger = (Tiger*)malloc(sizeof(Tiger));
    pTiger->pvft = & g_TigerVFT;
    pTiger->age = 3;
    sprintf(pTiger->name, "Tiger");

    printf("/n malloc ... /n");

    return (Animal*)pTiger;
}

static void _Destory(Animal * This)
{
    printf("/n ha, just free./n");
    free(This);
}

static void _SayHello(Animal * This, int n)
{
    Tiger * pTiger = (Tiger*)This;
    printf("/n %s hello %d /n", pTiger->name);
}

static void _SayHungry(Animal * This, char * food)
{
    Tiger * pTiger = (Tiger*)This;
    printf("/n %s want %s /n", pTiger->name, food);
}

Bear
/* Bear.hpp */

#ifndef __Bear_hpp__
#define __Bear_hpp__


#include "Animal.hpp"


class Bear : public Animal 
{
private:
    char _name[64];

public:
    virtual void Destroy(void);
    virtual void SayHello(int n);
    virtual void SayHungry(char * food);
 Bear();
 virtual ~Bear();

};


#endif


/* Bear.cpp */

#include <iostream>

#include "Bear.hpp"
#include "MICPP.hpp"


Animal * Bear_new(void)
{
    std::cout << std::endl << " new ..." << std::endl;
    return new Bear;
}

Bear::Bear()
{
    sprintf(_name, "Bear");
}

Bear::~Bear()
{

}

void Bear::Destroy(void)
{
    std::cout << std::endl << " oh, delete this now." << std::endl;
    delete this;
}

void Bear::SayHello(int n)
{
    std::cout << std::endl << _name << " hello " << n << std::endl;
}

void Bear::SayHungry(char * food)
{
    std::cout << std::endl << _name << " want " << food << std::endl;
}


 C 创建对象
 Tiger用的是C,需要C版的Animal;Bear用的是C++,需要C++版的Animal;

 

/* mic.h */

#ifndef __MIC_h__
#define __MIC_h__


#include "Animal.h"


#ifdef __cplusplus
extern "C" {
#endif


    Animal * Tiger_new(void);


#ifdef __cplusplus
}
#endif


#endif

 

/* micpp.h */

#ifndef __MICPP_h__
#define __MICPP_h__


#include "Animal.h"


#ifdef __cplusplus
extern "C" {
#endif


    Animal * Bear_new(void);


#ifdef __cplusplus
}
#endif


#endif

 

C++ 创建对象
/* mic.hpp */

#ifndef __MIC_hpp__
#define __MIC_hpp__


#include "Animal.hpp"


#ifdef __cplusplus
extern "C" {
#endif


    Animal * Tiger_new(void);


#ifdef __cplusplus
}
#endif


#endif


/* MICPP.hpp */

#ifndef __MICPP_hpp__
#define __MICPP_hpp__


#include "Animal.hpp"


#ifdef __cplusplus
extern "C" {
#endif


    Animal * Bear_new(void);


#ifdef __cplusplus
}
#endif


#endif

 

C 调用
#include "MIC.h"
#include "MICPP.h"


int main(int argc, char* argv[])
{
    Animal * pBear = 0;
    Animal * pTiger = 0;

    pTiger = Tiger_new();
    Animal_SayHello(pTiger, 3);
    Animal_SayHungry(pTiger, "duck");
    Object_Destroy(pTiger);

    pBear = Bear_new();
    Animal_SayHello(pBear, 3);
    Animal_SayHungry(pBear, "duck");
    Animal_Destroy(pBear);

 return 0;
}

C++调用
#include "MIC.hpp"
#include "MICPP.hpp"


int main(int argc, char* argv[])
{
    Animal * pTiger = Tiger_new();
    pTiger->SayHello(3);
    pTiger->SayHungry("duck");

    Object * pObj = pTiger;
    pObj->Destroy();

    Animal * pBear = Bear_new();
    pBear->SayHello(2);
    pBear->SayHungry("fish");
    pBear->Destroy();

 return 0;
}


调用结果
MSVC 60 的执行结果。


 malloc ...

 Tiger hello 1245056

 Tiger want duck

 ha, just free.

 new ...

Bear hello 3

Bear want duck

 oh, delete this now.


六 小结
C调用的时候,那个Object_Destroy是不是有多态的味道??宏定义实现了C的多态?

 

原创粉丝点击