从Java到C++——从union到VARIANT与CComVariant的深层剖析

我第一次用VARIANT和CComVariant的时候全然不明确它是怎么回事,为它什么数据类型都能够存放。什么数据都能够被能够初始化?里面究竟是怎么实现的?感觉又奇妙又迷惑!我们在上一节中讲了union的使用方法之后你或许想到了大概是怎么回事了。没错。union能够帮我们实现这一个奇妙的功能。并且VARIANT定义中确实使用了union。假设你还不明确,那我们就自己来模拟实现一个相似于CComVariant功能的类把,废话不多说,看代码:

CVariate.h:

#ifndef CVARIATE_H
#define CVARIATE_H

#include <string.h>

//======================================================
const unsigned int DEFAULT_STRLEN = 256;
//=======================================================

//自定义一个类用于存放随意类型的数据,以模拟类型VARIANT的功能。
class CVariate
{
public:
    CVariate() : type(INT), nVal(0){}               //默认构造函数。初始化nVal,值为0
    virtual ~CVariate(){};                          //虚构函数,不做不论什么处理
    CVariate(const CVariate& val) : type(val.type)  //拷贝构造函数
    {
        CopyUnion(val);
    }
    CVariate &operator=(char c)
    {
        type = CHAR;
        cVal = c;
        return *this;
    }
    CVariate &operator=(short int sn)
    {
        type = SHORT;
        snVal = sn;
        return *this;
    }
    CVariate &operator=(int i)
    {
        type = INT;
        nVal = i;
        return *this;
    }
    CVariate &operator=(long l)
    {
        type = LONG;
        lVal = l;
        return *this;
    }
    CVariate &operator=(float f)
    {
        type = FLOAT;
        fVal = f;
        return *this;
    }
    CVariate &operator=(double d)
    {
        type = DOUBLE;
        dVal = d;
        return *this;
    }
    CVariate &operator=(const char* str);
    void CopyUnion(const CVariate& val);                    //数据的拷贝
    void DisplayValue();
private:
    enum {CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, STR}type;  //为不同的数据类型定义一个枚举值
    union                                                   //union,能够存入各种类型的数据
    {
        char cVal;
        short snVal;
        int nVal;
        long lVal;
        float fVal;
        double dVal;
        char strVal[DEFAULT_STRLEN];
    };
};

#endif // CVARIATE_H

CVariate.cpp:

#include "../include/CVariate.h"
#include <iostream>

CVariate& CVariate::operator=(const char* str)
{
    if(strlen(str) >= DEFAULT_STRLEN)
    {
        std::cerr << "The length of string is out of memory." << std::endl;
    } else
    {
        strcpy(strVal, str);
        type = STR;
    }
    return *this;
}

void CVariate::CopyUnion(const CVariate& val)
{
    switch(val.type)
    {
        case CVariate::CHAR:
            cVal = val.cVal;
            break;
        case CVariate::SHORT:
            snVal = val.snVal;
            break;
        case CVariate::INT:
            nVal = val.nVal;
            break;
        case CVariate::LONG:
            lVal = val.lVal;
            break;
        case CVariate::FLOAT:
            fVal = val.fVal;
            break;
        case CVariate::DOUBLE:
            dVal = val.dVal;
            break;
        case CVariate::STR:
            if(strlen(val.strVal) >= DEFAULT_STRLEN)
            {
                std::cerr << "The length of string is out of memory." << std::endl;
                break;
            } else
            {
                strcpy(strVal, val.strVal);
            }
            break;
        default:
            return;
    }
}

void CVariate::DisplayValue()
{
    switch(type)
    {
        case CVariate::CHAR:
            std::cout << cVal;
            break;
        case CVariate::SHORT:
            std::cout << snVal;
            break;
        case CVariate::INT:
            std::cout << nVal;
            break;
        case CVariate::LONG:
            std::cout << lVal;
            break;
        case CVariate::FLOAT:
            std::cout << fVal;
            break;
        case CVariate::DOUBLE:
            std::cout << dVal;
            break;
        case CVariate::STR:
            char s[255];
            strcpy(s, strVal);
            std::cout << s;
            break;
        default:
            return;
    }
    std::cout << std::endl;
}

Test.cpp:

int main()
{
    CVariate cVal;
    cVal.DisplayValue();
    cVal = 125;
    cVal.DisplayValue();
    CVariate cVal2(cVal);
    cVal2.DisplayValue();
    cVal2 = 188.598;
    cVal2.DisplayValue();
    cVal2 = "Hello World.";
    cVal2.DisplayValue();
    return 0;
}

结果例如以下:

VARIANT的结构能够參考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义例如以下:

struct tagVARIANT {
union {
struct __tagVARIANT {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
ULONGLONG ullVal; ---VT_UI8
LONGLONG llVal; ---VT_I8
LONG lVal; ---VT_I4 */
BYTE bVal; ---VT_UI1 */
SHORT iVal; ---VT_I2 */
FLOAT fltVal; ---VT_R4 */
DOUBLE dblVal; ---VT_R8 */
VARIANT_BOOL boolVal;   ---VT_BOOL */
_VARIANT_BOOL bool; ---(obsolete) */
SCODE scode; ---VT_ERROR */
CY cyVal; ---VT_CY */
DATE date; ---VT_DATE */
BSTR bstrVal; ---VT_BSTR */
IUnknown * punkVal; ---VT_UNKNOWN */
IDispatch * pdispVal; ---VT_DISPATCH */
SAFEARRAY * parray; ---VT_ARRAY */
BYTE * pbVal; ---VT_BYREF|VT_UI1 */
SHORT * piVal; ---VT_BYREF|VT_I2 */
LONG * plVal; ---VT_BYREF|VT_I4 */
LONGLONG * pllVal; ---VT_BYREF|VT_I8 */
FLOAT * pfltVal; ---VT_BYREF|VT_R4 */
DOUBLE * pdblVal; ---VT_BYREF|VT_R8 */
VARIANT_BOOL *pboolVal; ---VT_BYREF|VT_BOOL */
_VARIANT_BOOL *pbool; ---(obsolete) */
SCODE * pscode; ---VT_BYREF|VT_ERROR */
CY * pcyVal; ---VT_BYREF|VT_CY */
DATE * pdate; ---VT_BYREF|VT_DATE */
BSTR * pbstrVal; ---VT_BYREF|VT_BSTR */
IUnknown ** ppunkValVARIANT的结构能够參考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。

struct tagVARIANT {

union {

struct __tagVARIANT {

VARTYPE vt;

WORD wReserved1;

WORD wReserved2;

WORD wReserved3;

union {

ULONGLONG ullVal; ---VT_UI8

LONGLONG llVal; ---VT_I8

LONG lVal; ---VT_I4 */

BYTE bVal; ---VT_UI1 */

SHORT iVal; ---VT_I2 */

FLOAT fltVal; ---VT_R4 */

DOUBLE dblVal; ---VT_R8 */

VARIANT_BOOL boolVal;   ---VT_BOOL */

_VARIANT_BOOL bool; ---(obsolete) */

SCODE scode; ---VT_ERROR */

CY cyVal; ---VT_CY */

DATE date; ---VT_DATE */

BSTR bstrVal; ---VT_BSTR */

IUnknown * punkVal; ---VT_UNKNOWN */

IDispatch * pdispVal; ---VT_DISPATCH */

SAFEARRAY * parray; ---VT_ARRAY */

BYTE * pbVal; ---VT_BYREF|VT_UI1 */

SHORT * piVal; ---VT_BYREF|VT_I2 */

LONG * plVal; ---VT_BYREF|VT_I4 */

LONGLONG * pllVal; ---VT_BYREF|VT_I8 */

FLOAT * pfltVal; ---VT_BYREF|VT_R4 */

DOUBLE * pdblVal; ---VT_BYREF|VT_R8 */

VARIANT_BOOL *pboolVal; ---VT_BYREF|VT_BOOL */

_VARIANT_BOOL *pbool; ---(obsolete) */

SCODE * pscode; ---VT_BYREF|VT_ERROR */

CY * pcyVal; ---VT_BYREF|VT_CY */

DATE * pdate; ---VT_BYREF|VT_DATE */

BSTR * pbstrVal; ---VT_BYREF|VT_BSTR */

IUnknown ** ppunkVal; ---VT_BYREF|VT_UNKNOWN */

IDispatch ** ppdispVal; ---VT_BYREF|VT_DISPATCH */

SAFEARRAY ** pparray; ---VT_BYREF|VT_ARRAY */

VARIANT * pvarVal; ---VT_BYREF|VT_VARIANT */

PVOID byref; ---Generic ByRef */

CHAR cVal; ---VT_I1 */

USHORT uiVal; ---VT_UI2 */

ULONG ulVal; ---VT_UI4 */

INT intVal; ---VT_INT */
VARIANT的结构能够參考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。

struct tagVARIANT {

union {

struct __tagVARIANT {

VARTYPE vt;

WORD wReserved1;

WORD wReserved2;

WORD wReserved3;

union {

ULONGLONG ullVal; ---VT_UI8

LONGLONG llVal; ---VT_I8

LONG lVal; ---VT_I4 */

BYTE bVal; ---VT_UI1 */

SHORT iVal; ---VT_I2 */

FLOAT fltVal; ---VT_R4 */

DOUBLE dblVal; ---VT_R8 */

VARIANT_BOOL boolVal;   ---VT_BOOL */

_VARIANT_BOOL bool; ---(obsolete) */

SCODE scode; ---VT_ERROR */

CY cyVal; ---VT_CY */

DATE date; ---VT_DATE */

BSTR bstrVal; ---VT_BSTR */

IUnknown * punkVal; ---VT_UNKNOWN */

IDispatch * pdispVal; ---VT_DISPATCH */

SAFEARRAY * parray; ---VT_ARRAY */

BYTE * pbVal; ---VT_BYREF|VT_UI1 */

SHORT * piVal; ---VT_BYREF|VT_I2 */

LONG * plVal; ---VT_BYREF|VT_I4 */

LONGLONG * pllVal; ---VT_BYREF|VT_I8 */

FLOAT * pfltVal; ---VT_BYREF|VT_R4 */

DOUBLE * pdblVal; ---VT_BYREF|VT_R8 */

VARIANT_BOOL *pboolVal; ---VT_BYREF|VT_BOOL */

_VARIANT_BOOL *pbool; ---(obsolete) */

SCODE * pscode; ---VT_BYREF|VT_ERROR */

CY * pcyVal; ---VT_BYREF|VT_CY */

DATE * pdate; ---VT_BYREF|VT_DATE */

BSTR * pbstrVal; ---VT_VARIANT的结构能够參考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。

struct tagVARIANT {

union {

struct __tagVARIANT {

VARTYPE vt;

WORD wReserved1;

WORD wReserved2;

WORD wReserved3;

union {

ULONGLONG ullVal; ---VT_UI8

LONGLONG llVal; ---VT_I8

LONG lVal; ---VT_I4 */

BYTE bVal; ---VT_UI1 */

SHORT iVal; ---VT_I2 */

FLOAT fltVal; ---VT_R4 */

DOUBLE dblVal; ---VT_R8 */

VARIANT_BOOL boolVal;   ---VT_BOOL */

_VARIANT_BOOL bool; ---(obsolete) */

SCODE scode; ---VT_ERROR */

CY cyVal; ---VT_CY */

DATE date; ---VT_DATE */

BSTR bstrVal; ---VT_BSTR */

IUnknown * punkVal; ---VT_UNKNOWN */

IDispatch * pdispVal; ---VT_DISPATCH */

SAFEARRAY * parray; ---VT_ARRAY */

BYTE * pbVal; ---VT_BYREF|VT_UI1 */

SHORT * piVal; ---VT_BYREF|VT_I2 */

LONG * plVal; ---VT_BYREF|VT_I4 */

LONGLONG * pllVal; ---VT_BYREF|VT_I8 */

FLOAT * pfltVal; ---VT_BYREF|VT_R4 */

DOUBLE * pdblVal; ---VT_BYREF|VT_R8 */

VARIANT_BOOL *pboolVal; ---VT_BYREF|VT_BOOL */

_VARIANT_BOOL *pbool; ---(obsolete) */

SCODE * pscode; ---VT_BYREF|VT_ERROR */

CY * pcyVal; ---VT_BYREF|VT_CY */

DATE * pdate; ---VT_BYREF|VT_DATE */

BSTR * pbstrVal; ---VT_BYREF|VT_BSTR */

IUnknown ** ppunkVal; ---VT_BYREF|VT_UNKNOWN */

IDispatch ** ppdispVal; ---VT_BYREF|VT_DISPATCH */

SAFEARRAY ** pparray; ---VT_BYREF|VT_ARRAY */

VARIANT * pvarVal; ---VT_BYREF|VT_VARIANT */

PVOID byref; ---Generic ByRef */

CHAR cVal; ---VT_I1 */

USHORT uiVal; ---VT_UI2 */

ULONG ulVal; ---VT_UI4 */

INT intVal; ---VT_INT */

UINT uintVal; ---VT_UINT */

DECIMAL * pdecVal; ---VT_BYREF|VT_DECIMAL */

CHAR * pcVal; ---VT_BYREF|VT_I1 */

USHORT * puiVal; ---VT_BYREF|VT_UI2 */

ULONG * pulVal; ---VT_BYREF|VT_UI4 */

ULONGLONG * pullVal; --- VT_BYREF|VT_UI8 */

INT * pintVal; ---VT_BYREF|VT_INT */

UINT * puintVal; ---VT_BYREF|VT_UINT

struct __tagBRECORD {

PVOID pvRecord;

IRecordInfo * pRecInfo;

} __VARIANT_NAME_4; --- VT_RECORD

} __VARIANT_NAME_3;

} __VARIANT_NAME_2;

DECIMAL decVal;

} __VARIANT_NAME_1;

};BYREF|VT_BSTR */

IUnknown ** ppunkVal; ---VT_BYREF|VT_UNKNOWN */

IDispatch ** ppdispVal; ---VT_BYREF|VT_DISPATCH */

SAFEARRAY ** pparray; ---VT_BYREF|VT_ARRAY */

VARIANT * pvarVal; ---VT_BYREF|VT_VARIANT */

PVOID byref; ---Generic ByRef */

CHAR cVal; ---VT_I1 */

USHORT uiVal; ---VT_UI2 */

ULONG ulVal; ---VT_UI4 */

INT intVal; ---VT_INT */

UINT uintVal; ---VT_UINT */

DECIMAL * pdecVal; ---VT_BYREF|VT_DECIMAL */

CHAR * pcVal; ---VT_BYREF|VT_I1 */

USHORT * puiVal; ---VT_BYREF|VT_UI2 */

ULONG * pulVal; ---VT_BYREF|VT_UI4 */

ULONGLONG * pullVal; --- VT_BYREF|VT_UI8 */

INT * pintVal; ---VT_BYREF|VT_INT */

UINT * puintVal; ---VT_BYREF|VT_UINT

struct __tagBRECORD {

PVOID pvRecord;

IRecordInfo * pRecInfo;

} __VARIANT_NAME_4; --- VT_RECORD

} __VARIANT_NAME_3;

} __VARIANT_NAME_2;

DECIMAL decVal;

} __VARIANT_NAME_1;

};
UINT uintVal; ---VT_UINT */

DECIMAL * pdecVal; ---VT_BYREF|VT_DECIMAL */

CHAR * pcVal; ---VT_BYREF|VT_I1 */

USHORT * puiVal; ---VT_BYREF|VT_UI2 */

ULONG * pulVal; ---VT_BYREF|VT_UI4 */

ULONGLONG * pullVal; --- VT_BYREF|VT_UI8 */

INT * pintVal; ---VT_BYREF|VT_INT */

UINT * puintVal; ---VT_BYREF|VT_UINT

struct __tagBRECORD {

PVOID pvRecord;

IRecordInfo * pRecInfo;

} __VARIANT_NAME_4; --- VT_RECORD

} __VARIANT_NAME_3;

} __VARIANT_NAME_2;

DECIMAL decVal;

} __VARIANT_NAME_1;

};; ---VT_BYREF|VT_UNKNOWN */
IDispatch ** ppdispVal; ---VT_BYREF|VT_DISPATCH */
SAFEARRAY ** pparray; ---VT_BYREF|VT_ARRAY */
VARIANT * pvarVal; ---VT_BYREF|VT_VARIANT */
PVOID byref; ---Generic ByRef */
CHAR cVal; ---VT_I1 */
USHORT uiVal; ---VT_UI2 */
ULONG ulVal; ---VT_UI4 */
INT intVal; ---VT_INT */
UINT uintVal; ---VT_UINT */
DECIMAL * pdecVal; ---VT_BYREF|VT_DECIMAL */
CHAR * pcVal; ---VT_BYREF|VT_I1 */
USHORT * puiVal; ---VT_BYREF|VT_UI2 */
ULONG * pulVal; ---VT_BYREF|VT_UI4 */
ULONGLONG * pullVal; --- VT_BYREF|VT_UI8 */
INT * pintVal; ---VT_BYREF|VT_INT */
UINT * puintVal; ---VT_BYREF|VT_UINT
struct __tagBRECORD {
PVOID pvRecord;
IRecordInfo * pRecInfo;
} __VARIANT_NAME_4; --- VT_RECORD
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
};

相关说明參考文章:

http://blog.csdn.net/nppg2008/article/details/7885139

http://blog.csdn.net/china_chentao/article/details/4059698

时间: 2024-08-11 03:28:48

从Java到C++——从union到VARIANT与CComVariant的深层剖析的相关文章

Java使用foreach遍历集和时不能add/remove的原因剖析

foreach 与 Iterator 我们知道,在Java中使用foreach对集和进行遍历时,是无法对该集和进行插入.删除等操作,比如以下代码: for(Person p : personList){ if(StringUtil.isBlank(p.getName())){ personList.remove(p); } } 执行代码,报以下异常: Exception in thread "main" java.util.ConcurrentModificationException

谈ATL(四)--VARIANT类型与CComVariant

ATL为了更好的让用户体验便捷并使程序的接口参数更加通用.灵活,引入了一种叫做VARIANT的数据类型,这个类型是通过一个结构体来定义的,如果不仔细阅读VARIANT结构体的定义,那么就不能体会编写者的良苦用心,更无法体会CComVariant设计的美妙,有时候用艺术的眼光欣赏程序,他们并不枯燥,相反他们真的很美. 下面是VARIANT结构体的定义,该定义在<OAIDL.h>中. typedef struct tagVARIANT VARIANT; struct  tagVARIANT   

Boost--variant (C++中的union)

union联合体类型的问题 只能用于内部类型,这使得union在C++中几乎没有用 所以boost提供了variant,相当于是C++中的union #include "boost/variant.hpp" #include <vector> #include <iostream> #include <array> #include <string> using namespace std; class DoubleVisitor : p

Java开源项目(备查)

转自:http://www.blogjava.net/Carter0618/archive/2008/08/11/221222.html Spring Framework  [Java开源 J2EE框架] Spring 是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯.Spring的架构基础是基于使用JavaBean属性的 Inversion of Control容器.然而,这仅仅是完整图景中的一部分

Java 垃圾回收机制概述

摘要: Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题:给对象分配内存 以及 回收分配给对象的内存,而且这两个问题针对的内存区域就是Java内存模型中的 堆区.关于对象分配内存问题,笔者的博文<JVM 内存模型概述>已经阐述了 如何划分可用空间及其涉及到的线程安全问题,本文将结合垃圾回收策略进一步给出内存分配规则.垃圾回收机制的引入可以有效的防止内存泄露.保证内存的有效使用,也大大解放了Java程序员的双手,使得他们在编写程序的时候不再需要考虑内存管理.本文着重

Java应用Tomcat执行过程之性能调优

Java应用Tomcat执行过程之性能调优(整理两天时间.转载请注出处) 1.简介 Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和JavaServer Page(JSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台.安全域管理和Tomcat阀等. Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并

【转】44款Java 网络爬虫开源软件

原帖地址 http://www.oschina.net/project/lang/19?tag=64&sort=time 极简网络爬虫组件 WebFetch WebFetch 是无依赖极简网页爬取组件,能在移动设备上运行的微型爬虫. WebFetch 要达到的目标: 没有第三方依赖jar包 减少内存使用 提高CPU利用率 加快网络爬取速度 简洁明了的api接口 能在Android设备上稳定运行 小巧灵活可以方便集成的网页抓取组件 使用...更多WebFetch信息 开源爬虫框架 Guozhong

Java动态代理 深度详解

代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常简单易懂的例子向大家介绍动态代理的两种类型,接着重点介绍动态代理的两种实现方式(Java 动态代理和 CGLib 动态代理),最后深入剖析这两种实现方式的异同,最后说说动态代理在我们周边框架中的应用. 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们都是使用蛋糕机来做蛋糕的,而且不同种类的蛋糕

IDEA Maven项目 编译的问题

IDEA中,点击项目的maven插件的 compile: 出现: [INFO] ------------------------------------------------------------------------[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project j360-deliver: Compi