成都网站建设设计

将想法与焦点和您一起共享

C++类型萃取(分文件管理)

类型萃取
类型萃取是基于c++中的模板特化来实现的,是对于模板特化的应用。

成都创新互联2013年至今,是专业互联网技术服务公司,拥有项目成都做网站、成都网站设计网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元绥化做网站,已为上家服务,为绥化各地企业和个人服务,联系电话:18980820575

以通用的拷贝函数为例

拷贝函数,c++自带的拷贝函数是俗称的浅拷贝,浅拷贝对于一些内置类型而言不会出错,但对于一些自定义类型在拷贝的时候就会出现内存访问错误(中断),想回顾浅拷贝的“同志”可以看https://blog.51cto.com/14233078/2442527
1.此方案虽然解决了拷贝问题,但是缺点也很明显,在每一次拷贝数据,都需要遍历一遍,时间复杂度O(1)

#include
using namespace std;
#include

template
void Copy1(T* dst, T* src, size_t size)
{
    memcpy(dst, src, sizeof(T)*size);
}

// 优点:一定不会出错
// 缺陷:O(N)
template
void Copy2(T* dst, T* src, size_t size)
{
    for (size_t i = 0; i < size; ++i)
        dst[i] = src[i];
}

bool IsPODType(const char* strType)
{
    // 此处可以将所有的内置类型枚举出来
    const char* strTypes[] = { "char", "short", "int", "long", "long long", "float", "double" };
    for (auto e : strTypes)
    {
        if (strcmp(strType, e) == 0)
            return true;
    }

    return false;
}

template
void Copy(T* dst, T* src, size_t size)
{
    // 通过typeid可以将T的实际类型按照字符串的方式返回
    if (IsPODType(typeid(T).name()))
    {
        // T的类型:内置类型
        memcpy(dst, src, sizeof(T)*size);
    }
    else
    {
        // T的类型:自定义类型---原因:自定义类型中可能会存在浅拷贝
        for (size_t i = 0; i < size; ++i)
            dst[i] = src[i];
    }
}

void TestCopy()
{
    int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int array2[10];
    Copy(array2, array1, 10);

    string s1[3] = { "1111", "2222", "3333" };
    string s2[3];
    Copy(s2, s1, 3);
}

int main()
{
    TestCopy();
    return 0;
}

C语言参与编译的是.c文件,一个.c文件是一个编译单元。
头文件在预处理阶段被展开,即,预处理器看见#include预处理指令的时候,就用相应头文件的内容替换掉这个#include预处理指令(把头文件内容拷贝到.c文件中,然后删除这条#include预处理指令)。
你应该把头文件看出是导出给外部模块使用的接口,里面存放外部模块需要使用的宏定义及函数原型。
在linux下,可以用gcc -E查看预处理之后的文件。
头文件中的函数原型是提供给编译器作为函数原型检查的,对于不是本源文件中的函数,编译过程中并不会产生实际的调用代码(函数调用需要知道确切的函数地址),只是在相应的地方做个标记,表示在这里需要调用某个函数。编译完成产生的是汇编代码。
如上所述,编译产生的汇编代码并不能直接运行,因为外部函数调用的地方还没给予确切的函数地址。这个工作由链接过程完成。链接器会查找其它源文件所产生的汇编代码,进而找到正确的函数调用地址,然后用这个地址替换掉在编译时做的标记。完成这一步后,程序就可以实际运行了。
因此,.h是根本不会被编译的,它如果被包含,则会被预处理器将其内容一分不差的拷贝到.c文件中,.编译器编译的是拷贝后的这个.c文件。

2.分文件管理:
因为头文件在预处理阶段就已完成,所以不会降低代码效率,因此解决1中代码效率低的问题

头文件

#pragma once

#include
using namespace std;
#include

//来自自定义类型
struct TrueType
{};

// 对应自定义类型
struct FalseType
{};

//隐示实例化
template
struct TypeTraits
{
    typedef FalseType PODTYPE;  // plain old data
};

//显示实例化
template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};

template<>
struct TypeTraits
{
    typedef TrueType PODTYPE;
};

void TestCopy();

源代码

#include"Type_extraction.h"

template
void Copy(T* dst, T* src, size_t size, TrueType)
{
    // T的类型:内置类型
    memcpy(dst, src, sizeof(T)*size);
}

template
void Copy(T* dst, T* src, size_t size, FalseType)
{
    // T的类型:自定义类型---原因:自定义类型中可能会存在浅拷贝
    for (size_t i = 0; i < size; ++i)
        dst[i] = src[i];
}

template
void Copy(T* dst, T* src, size_t size)
{
    Copy(dst, src, size, TypeTraits::PODTYPE());
}

void TestCopy()
{
    int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int array2[10];
    Copy(array2, array1, 10);

    string s1[3] = { "1111", "2222", "3333" };
    string s2[3];
    Copy(s2, s1, 3);
}

测试文件main.c

#include"Type_extraction.h"

int main()
{
    TestCopy();
    return 0;
}

模板的声明和定义必须放在一个文件原因
https://blog.csdn.net/chigusakawada/article/details/78752668
显示实例化,隐式实例化概念
https://blog.csdn.net/qiujianjian/article/details/84792608


新闻名称:C++类型萃取(分文件管理)
网页路径:http://chengdu.cdxwcx.cn/article/gjdejp.html